UniApp 小程序开发技巧
这里是最近基于 vue2.x 的 uniapp 小程序开发过程中的一些技巧汇总,希望可以给到刚刚入门uniapp开发的同学一些帮助。
1. 使用 easycom 简化自定义模块导入
easycom
介绍
传统vue组件,需要安装、引用、注册,三个步骤后才能使用组件。easycom
将其精简为一步。 只要组件安装在项目的 components
目录下,并符合 components/
组件名称/组件名称.vue目录结构。就可以不用引用、注册,直接在页面中使用。不管 components
目录下安装了多少组件,easycom
打包后会自动剔除没有使用的组件,对组件库的使用尤为友好。官方介绍
项目中用到的全局公共组件可以使用 easycom 的方式自动引用,而且可以按需打包,十分方便,提升开发效率
自定义的包为 tj-ui
,相关的组件放到 tj-ui/components
下
目录结构
├── uni_modules
├── tj-ui
│ └── components
│ ├── tj-description
│ ├── tj-description-item
│ └── tj-section
组件以正常的组件写法相同,没有什么不一样,但要注意多端的兼容
配置
在根目录下 /pages.json
中配置导入的模块路径规则
{
...
"easycom": {
"autoscan": true,
"custom": {
"^tj-(.*)": "@/uni_modules/tj-ui/components/tj-$1/tj-$1.vue",
}
}
}
使用
- 需要重新运行项目或重启Hbuilder
- 注意组件标签的名称要与
tj-ui/components
下的名称一致
<tj-section>
<tj-description>
<tj-description-item title="检查时间" :rightText="examDate" border />
<tj-description-item title="订单金额" :rightText="orderPrice" border />
<tj-description-item title="收据金额" :rightText="selfMoney" />
</tj-description>
</tj-section>
2. request 请求封装
接口请求主要解决以下几个问题
- 更简洁的接口定义
- 支持配置为全局和本地处理异常
- 支持配置为全局和本地处理loading
- 支持配置post请求体的数据类型为 默认的请求体类或JSON
- 登录失效后自动跳转到授权登录页面,登录后回跳回来
接口定义
import registApi from './request'
const apiConfig = {
login: 'post /login',
deleteOrder: (orderId) => `delete /order/${orderId}`
}
const api = registApi(apiConfig, '/api')
export defalut api;
应用场景
import api from '@/api'
// - 默认值:没有loading、全局处理异常、请求体为 json
api.login({ data })
// - 全局处理异常
// 如果出现异常返回 永不结束的promise
// 1. 防止抛出 `Uncaught (in promise)` 异常
// 2. 使用时结合 async await 不需要 try...catch 来捕获异常
api.login({ data, catchError: false })
// - 全局显示loading
api.login({ data, loading: true })
// - 本地处理loading和异常
api.login({
data,
// 本地处理loading
loading: isLoading => {
this.isLoading = isLoading;
},
catchError: false
}).catch(err => {
// 处理异常
})
// - 使用表单提交,content-type 设置为 application/x-www-form-urlencoded
api.login({ data, dataType: 'default' })
异常的分类和处理
从接口返回的数据大致可以区分两种异常:业务异常 和 网络异常
- 网络异常:超时、服务器5xx、无网络
- 业务异常:请求体格式错误、正常的是业务异常提示如: 用户名密码不正确等
网络异常始终全局提示,此时应该中断后续业务逻辑
业务异常分两种,一种只是提醒没有后续逻辑,一种是提醒,点击后有后续逻辑,前一种可以全局处理,后一种需要具体业务具体处理,要本地处理,catchError
要设置为 false
3. 项目目录结构设计
.
├── api // 接口定义
├── components // 自定义的公共组件
├── docs // 项目文档
├── env.js // 环境配置
├── mixins // 公共Mixin
├── node_modules
├── pages // 页面分包 - 主包
├── pages_exam // 页面分包 - 子包
├── pages_hospital // 页面分包 - 子包
├── plugins // 挂载在Vue原型上的插件
├── service // 公共的业务逻辑
├── static // 静态资源
├── store // Vuex数据层
├── uni_modules // easycom 模块
├── utils // 工具层
4. 路由拦截封装
要封装的功能点:
- 提供一致的路由跳转方法,内置部分固定逻辑
- 提供登录状态校验
- 提供跳转参数封装
小程序提供的几种页面跳转方式:
uni.navigateTo 保留当前页面,跳转到应用内的某个页面,使用uni.navigateBack可以返回到原页面
uni.redirectTo 关闭当前页面,跳转到应用内的某个页面
uni.reLaunch 关闭所有页面,打开到应用内的某个页面
uni.switchTab 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
uni.navigateBack 关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages() 获取当前的页面栈,决定需要返回几层。
统一使用 this.$$routerTo(path, params, { auth: false, redirect: false })
来跳转页面,后面两个参数可选
path
可以是小程序页面路径,也可以是外部地址
1. 登录认证
例: this.$$routerTo('/pages/order/order', {}, { auth: true })
,方法内部会检查用户状态
这里的实现方式是多样的,不同的业务有不同的实现,这里我的实现是,用户登录后,在storage中存储一个标识,标识为true则已登录,为false则未登录,未登录用户需要跳转到授权登录页面或账号密码登录页面,跳转的时候需要带上回跳地址
if(auth === true && uni.getStorageSync('isLogin') === false){
routerTo('/pages/authorized/authorized', { nextUrl: encodeURIComponent(buildPath(path, paramas)) })
}
2. tabar页面
tabbar 页面
的特殊情况:不能带参数,只能使用 uni.switchTab
切换
tabbar页面可根据路径来判断是否是tabbar页面
如果需要带参数到tabbar页面,可以在跳转之前缓存数据,到tabbar页面后,从 onShow
中读取缓存数据,并清空缓存
// Tabar页面
if(pagePath.startsWith('/pages/tabbar')){
// 如果是tabar,则使用 switchTab, 并缓存tabbar跳转参数到本地
if(paramas) saveTabbarData(paramas);
uni.switchTab({ url: pagePath })
return;
}
3. 外部地址
外部地址的跳转:以 http
开头的地址应该跳转到 webivew
页面打开
if(path.startsWith('http')){
const webviewPath = '/pages/webview/webview?url='+encodeURIComponent(path) + '&' + obj2Params(paramas);
uni.navigateTo({ url: webviewPath})
return;
}
4. 重定向
例: this.$$routerTo('/pages/home/home', {}, { redirect: true })
如果是重写向则使用 uni.redirectTo
否则使用 uni.navigateTo
跳转
5. 全局挂载工具方法
将工具方法全局挂载到 Vue 原型上,方便业务调用
this.$$apis.login();
this.$$routerTo()
import apis from '@/api/index.js'
import { routerTo } from '@/utils/router.js'
const plugins = {
install: Vue => {
Vue.prototype.$$apis = apis;
Vue.prototype.$$routerTo = routerTo;
}
}
export default plugins;
import Vue from 'vue'
imoprt plugins from '@/plugins'
Vue.use(plugins);
转载自:https://juejin.cn/post/7110143045575639077