当前位置:   article > 正文

uniapp多端构建实战初探_uni-extend

uni-extend

一、背景

小程序具有跨平台、体验好、高灵活性以及即用即走、无需下载安装诸多优势。随着微信团队推出微信小程序,国内各大互联网团队也相继推出了各自的小程序,手机厂商也联合推出了快应用。但由于各种原因,各团队的小程序,并没有形成统一的标准或联盟,导致部分平台差异化大,要实现多个平台的小程序就得写多套小程序代码,这给开发者和企业带来不少额外的负担。这种情况下,一个多端统一的解决方案就显得尤为重要。统一多端标准后,让一处代码,多处运行成为了可能,而uniapp作为国内小程序的开创者,也制定了一套基于Vuejs的解决方案,并跻身前列,成为多端构建解决方案的优秀者之一。

快递100作为中国领先的快递物流信息服务商,在国内各大小程序平台均有发布小程序应用(微信百度支付宝头条QQQQ浏览器美团等)。在迭代的过程中,保持多个平台业务和体验一致十分必要。目前,快递100已实现了多端统一。以下分别为微信小程序、头条小程序和百度小程序二维码,你可以扫码(或者在各个客户端搜索快递100)进行体验。

                  

二、多端构建方案选型

目前多端构建有不少的解决方案,在比较了多种构建方案后,快递100团队将筛选目标锁定在了Tarouniapp两个解决方案上。关于多端构建解决方案如何选型,我们会考虑以下几个维度:

  • 框架的生态及其社区的大小
  • 框架的性能
  • 框架的学习成本与开发成本
  • 框架支持构建的应用端(如是否支持快应用和QQ小程序)
  • 团队的技术栈的匹配程度

基于以上的维度结合快递100开发团队的实际情况,经过多轮评审和调研后,我们团队最终选择了uniapp。尽管uniapp已经做得足够优秀,但是在实战开发的过程中依然会遇到这样那样的棘手的问题。本文将从零到一搭建一个简单的应用,解决实战过程中遇到的各种问题,并实现稳定的发布到所有的小程序端。

本文不会介绍uniapp相关API与组件的使用,也不会介绍Vue生态具体的使用方法,相关内容可以参考uniapp官网文档以及Vue官网文档。

文章主要包括以下几个方面的内容:

  • 项目的安装
  • 全局API封装
  • 路由拦截
  • 实现Vuex
  • 数据通信方案
  • 登录与用户信息示例
  • 自定义组件说明
  • 常见问题解决方法

三、项目搭建

(一) 创建项目

uni-app支持通过 可视化界面、vue-cli命令行 两种方式快速创建项目。本文将通过以HBuilderX 可视化界面创建项目为例,从零到一搭建起一个完整的项目。安装的方法请查看uniapp官网文档之快速上手

使用uniapp内置组件模板创建后的目录结构如下:

在这里插入图片描述

各目录和文件说明如下:

  • components: 公共组件目录,默认内置了uniapp的官方扩展组件,应用的公共组件也将放置在该目录下
  • pages: 业务页面目录,一个页面对应小程序的一个页面路由
  • static: 存放应用引用静态资源(如图片、视频等)的目录,静态资源只能存放在此目录,该目录下的内容不会经过编译
  • App.vue: 全局应用文件,用于配置全局样式、全局生命钩子等
  • main.js: 应用初始化文件,一般全局的扩展均在该文件实现
  • mainfest.json: 应用配置文件,主要包含各个小程序的appid、版本号等信息
  • pages.json: 路由配置,主要配置应用的页面路由、外观等
  • uni.scss: 全局的scss变量文件,在该文件定义的scss变量全局可用

安装后通过HBuilderX运行到微信小程序(需要配置微信开发者工具的路径),效果如下:

在这里插入图片描述

接下来让我们一步一步来完善整个应用。

(二)自定义全局API

在开发的过程中,我们经常需要重复的使用一些方法,如http请求相关的方法,通常我们会将这些方法封装为统一的模块。在这里,我们把公共的方法统一放到项目根目录下的utils目录下。

1. 反馈类UI相关API封装

用户操作的过程中,经常需要一些操作反馈,如toast,modal等。不同的应用一般都有不同的默认反馈(如文案、字体颜色等),我们首先来封装一下这些方法,相对比较简单。

在utils目录下创建interactiveFeedback.js文件

(1)toast

第一步,新建showToastmodal方法,如下:

// toast反馈
export function showToast(content = '', duration = 1500, icon = 'none') {
   
  uni.showToast({
   
    title: content,
    icon: icon,
    mask: true,
    duration: duration
  })
}

// 弹窗反馈
export function modal(content = '', opts = {
    showCancel: true }) {
   
  return new Promise((resolve, reject) => {
   
    uni.showModal({
   
      title: opts.title || '提示',
      content: content,
      cancelText: (opts.cancelText || '取消').slice(0, 4),
      confirmText: (opts.confirmText ||  '确定').slice(0, 4),
      cancelColor: opts.cancelColor || '#bebebe',
      confirmColor: opts.confirmColor || '#317ee7',
      showCancel: opts.showCancel !== false,
      success: res => {
   
        if (res.confirm) {
   
          resolve()
        } else if (res.cancel) {
   
          opts.handleCancel === true && reject()
        }
      }
    })
  })
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

在小程序中,confirmTextcancelText长度最长为4个字符,以上modal方法遵循promise规范

第二步,定义install方法

function install(Vue) {
   
  Vue.prototype.$toast = showToast
  Vue.prototype.$modal = modal
}
  • 1
  • 2
  • 3
  • 4
  • 5

可以根据实际情况定义更多的方法,如loadinghideLoading

第三步,导出相关的方法

export default {
    install }
  • 1
  • 2

第四步,打开main.js文件,安装模块

import interactiveFeedback from '@/utils/interactiveFeedback'

Vue.use(interactiveFeedback)
  • 1
  • 2
  • 3

安装后,我们就可以用以下的方式使用:

this.$toast("这是一个吐司提示")
this.$modal("这里是弹窗的提醒内容", {
   
	confirmText: "我知道了",
	handleCancel: true
}).then(() => {
   
	console.log("确定了")
}).catch(() => {
   
	console.log('取消了')
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
2. http请求封装

http模块专门用来做接口请求,通常一个应用中接口都会有公共的参数、请求头、授权信息等,将这些信息统一封装非常有必要。由于项目上经常要用到一些常量等,因此,我们先项目根目录下创建config.js文件,用于配置项目上使用的一些常量(如请求超时、接口服务器地址、小程序appid等),这里不一一列举,参照项目源码的config.js文件

接着在utils目录下创建request.js文件

第一步,引入常量和其他公共方法配置

import store from '@/store'
import {
    showToast } from './interactiveFeedback.js'
import {
   
  API_BASE,
  NETWORK_TIMEOUT,
  DEFAULT_ERR_MESSAGE,
  PLATFORM,
  NETWORK_ERR_MESSAGE
} from '@/config'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

第二步,定义两个核心处理方法

/**
 * 基本的http请求
 * @param {url: String} 请求的链接
 * @param {opts.data: Object} 请求的参数
 * @param {opts.needAuth: Boolean } 是否需要登录
 * @param {opts.handleFail: Boolean} 是否处理错误信息,设置为false将忽略请求时的错误
 * @param {opts.accessToken: Boolean} 是否将token覆盖为提供商token
 * */
export async function request(url, opts = {
   }) {
   
  opts.data = opts.data || {
   }
  if (opts.needAuth) {
   
    const userinfo = await store.dispatch('user/getUserInfo') // 获取用户信息
    opts.data.openid = store.getters.openid
    opts.data.token = store.getters.token
    opts.data.unionid = store.getters.unionid
  }
  return handleRequest(url, opts)
}

/**
 * 请求处理
*/
async function handleRequest(url, opts, isUpload) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/759288
推荐阅读