背景
在使用 uni-app 开发项目时,路由跳转是极为频繁的操作,uni-app 提供的路由跳转 api uni.navigateTo够用但是却不够好用,主要问题在于,实际业务中经常涉及大量对象传参的情况,而 uni-app 只支持 query 参数,这就导致,对于对象的传参,必须通过encodeURIComponent先编码,然后在新的页面再通过decodeURIComponent进行解码,为了编码 url,还要拼接&,导致一个页面跳转传参又臭又长,可读性还很差,比如像下面这样:
js
uni.navigateTo({
url: '/pages/test/pay?question_id=' +
res.data.id + '&service=' +
encodeURIComponent(JSON.stringify(
service)) + '&doctor=' +
encodeURIComponent(
JSON.stringify({
name: this.doctor.name,
dept_name: this.doctor
.dept_name,
dept_code: this.doctor
.dept_code,
code: this.doctor.code
})) + '&description=' +
encodeURIComponent(desc)
})
光看着就头大,要增加一个传参或者修改一个传参,都很考察眼力,寻找拼接的位置,获取参数的时候,也很鸡肋:
js
onLoad: function(query) {
this.pageHeight = uni.getSystemInfoSync().windowHeight
this.question_id = query.question_id
this.service = JSON.parse(decodeURIComponent(query.service.replace(/%/g, '%25')))
this.doctor = JSON.parse(decodeURIComponent(query.doctor.replace(/%/g, '%25')))
this.description = decodeURIComponent(query.description.replace(/%/g, '%25'))
}
由此,解决这一痛点就势在必行了,项目中虽然使用了u-view框架,提供了$u.route的方法,对 uni-app 的路由跳转方法进行简单的封装,可以支持通过第二个参数以对象的方式传参:
js
this.$u.route({
url: 'pages/components/empty/index',
params: {
name: 'lisa'
}
})
其优点是,对路由跳转传参友好了一点,看起来更简洁些,但是也仅此而已了,存在的缺陷也很大,主要在于:
- 仅支持值类型的传参,不支持引用类型传参,仍旧未解决实际业务中对对象数据传参的需要。
- 阉割版的封装,无法传递
events,对实际业务中页面返回的回调无法监听。
但u-view也启发了我对路由封装的一些思路,结合对axios的使用,我对uni-app的路由跳转方法进行了定制化的封装,并单独发布了包caring-route,且成功在业务中使用,基本解决了上述问题。
caring-route 的特点
- 继承了
uni-app的所有路由跳转方法,更加方便调用,名称更简洁 - 支持跳转
tabBar页面 - 支持
events - 支持成功失败回调
- 支持传递引用类型路由参数
- 支持解析路由参数
- rollup打包压缩,体积更小,仅有
2.7kb - 支持跳转小程序
支持两种调用方法
- 函数调用:
route(url[,config]) - 类的实例方法调用:
route[method](url[,params])
method的类型:
-
tobacktabredirectlaunchmini跳转小程序query解析路由参数
快速上手
安装
bash
npm i caring-route
使用
vue
html
<script>
import route from 'caring-route'
route('/pages/index/home')
</script>
基础使用
对于不需要传递参数的路由跳转,route函数提供了原生的方法名称和简化的方法名称,并支持两种传参方式:
一种是类似u-view的,传递两个参数route(url,data),第一个参数url就是要跳转的路由,第二个参数data则是要传递的参数,与$u.route的区别就是支持传递对象参数,是其加强版,当只需要跳转路由和传递参数时,推荐优先使用route(url,data)的调用方式。
第二种是类uni-app的调用方法,传递一个参数route(config),其基本使用和 uni-app 是相同的,区别在于:
uniapp中参数需要通过query参数拼到 url 上,而route(config)的url只传递跳转的页面路径即可,其页面参数用data或者params来接收。uniapp中需要通过不同的方法navigateTo、redirectTo等来执行不同的路由跳转,而route(config)支持type参数来指定跳转类型是navigateTo还是redirectTo
下面具体说明
传递两个参数route(url,data)的使用方法
对于uni.navigateTo的封装
这个方法是路由跳转中最常使用的 api,caring-route做了三种方法的封装,三个方法是等价的,实际业务中,直接使用route()函数是最方便的
js
// uni.navigateTo
route('/pages/index/home')
route.to('/pages/index/home')
route.navigateTo('/pages/index/home')
对于uni.redirectTo的封装
js
// redirectTo
route.direct('/pages/index/home')
route.redirectTo('/pages/index/home')
对于uni.reLaunch的封装
js
route.launch('/pages/index/home')
route.reLaunch('/pages/index/home')
对于uni.navigateBake的封装
js
// back
route.back(delta)
route.navigateBake(delta)
对于uni.switchTab的封装
js
// switchTab
route.tab('pages/index/index')
route.switchTab('pages/index/index')
传递路由跳转参数
route函数传入第二个参数,类型为对象,即为传递的路由参数,
js
route('/pages/index/home', {
name: 'wanko',
age: '25',
hoby: {
guitar: {
level: 1
}
}
})
route.to('/pages/index/home', {
name: 'wanko',
age: 25,
hoby: {
guitar: {
level: 1
}
}
})
route.launch('pages/index/index', {
msg: 'relunch过来'
})
route.redirect('/pages/index/home', {
msg: 'redirect过来'
})
传递一个参数route(config)的使用方法
js
route({
url:'/pages/index/home',
type: 'navigateTo',// 默认的跳转方式,可不传
data: {
name: 'wanko',
age: 25,
hoby: {
guitar: {
level: 1
}
},
arr: [1, 2, 3, 4, 5],
arrObj: [
{
name: 'wanko'
},
23,
'age'
]
},
events: {
onSuccess: (data) => {
console.log('onSuccess', data)
}
}
})
监听events事件
js
// A页面
route({
type: 'navigateTo', // 如果是navigateTo,可以不传type
url: '/pages/index/home',
events: {
onSuccess: (data) => {
console.log('onSuccess', data)
}
},
})
// B页面
const eventChannel = this.getOpenerEventChannel();
eventChannel.emit('onSuccess', {
data: 'data from home'
})
route.back()
获取路由参数
在onLoad中使用route的 query 方法传入 options ,函授调用的返回值为已经解码的路由参数
js
onLoad(options) {
const query = route.query(options)
}
处理跳转成功的回调
使用函数调用方式,添加 .then
js
route('pages/index/index').then(res => console.log('跳转成功'))
跳转微信小程序
使用 mini(appId, path) 方法来跳转微信小程序
js
route.mini('wx-appid', 'pages/tabbar/components').then(() => {
console.log('跳转成功')
})