利用路由守卫控制入口权限
在实际研发过程中,会有很多页面需要控制权限,比如只有登录用户才能访问的页面,或者只有管理员才能访问的页面。这些都可以通过路由守卫来实现。Anim 框架提供了路由守卫的功能,可以很方便的实现这些功能。我们来看看在最佳实践场景下,该如何使用路由守卫能力。
页面权限控制
下面我们看一下模版中的例子
原本是跳转到 /pages/permission/redirect
实际上被 Anim Router 重定向到了 /page/permission/index
而未登录展示模态框,在未登录时点击,则会出现事先配置好的模态框。
路由守卫的优势
可以看到,我们在实际上的业务代码中,并没有对与特定的路由进行业务逻辑的检测。这使得我们的业务逻辑非常的干净,只需要关注正常情况下,这个路由要跳转到什么地方。这样我们可以从复杂的业务流程代码中解放开,不同的页面在进行该路由跳转时,都无需再重复判断跳转逻辑。而且最重要的一点是,我们可以避免忘记写跳转逻辑导致页面被错误打开,因为该跳转逻辑是基于最底层的 wx.navigateTo
与wx.redirectTo
。
对有需要在路由跳转前做全局的前置业务逻辑判断的,都可以采用这类代码模式。在实际业务过程中,可能会采用业务状态 + 全局状态的混合使用方式,来达到最佳的效果。
代码比对
在实际业务下,当我们遇到了业务状态+全局状态需要进行逻辑判断后进行路由跳转时。
我们的需求如下:
- 当我们未登录时,跳转到
/pages/permission/no-permission
- 当我们全局数据中的
isSelected
为false
时,跳转到/pages/permission/no-selected
- 如果都正常,则跳转到
/pages/permission/index
- 页面 B 中,大部分逻辑如上,但是包含自己一个特殊的逻辑,当
BData
为something
时,则需要弹出模态框不做跳转。
⚠️未采用路由守卫能力
不同页面进行逻辑跳转时,都会加入大量的业务代码进行判断。虽然我们可以进行逻辑封装,一定程度缓解这个事情。但是如果遇到其他同学忘记了使用该封装的方法,就会导致页面被错误打开。
// pages/a.js
// 页面 A
Anim.Page({
// ...省略部分代码
handleNavigateTo(){
if(userStore.isLogin()){
if(!!getApp().globalData.isSelected){
wx.navigateTo({
url: '/pages/permission/index'
})
} else {
wx.navigateTo({
url: '/pages/permission/no-selected'
})
}
} else {
wx.navigateTo({
url: '/pages/permission/no-permission'
})
}
}
})
另一个页面仍然要包含相同的逻辑判断,甚至可能会出现判断逻辑遗漏的情况。
// pages/b.js
// 页面 B
Anim.Page({
// ...省略部分代码
handleNavigateTo(){
if(userStore.isLogin()){
// ERROR: 遗漏了判断 isSelected 逻辑
if(this.data.BData === 'something'){
wx.showModal({
title: '温馨提示',
content: 'BData 为 something',
showCancel: false,
});
} else {
wx.navigateTo({
url: '/pages/permission/index'
})
}
} else {
wx.navigateTo({
url: '/pages/permission/no-permission'
})
}
}
})
✅采用路由守卫能力
// pages/a.js
// 页面 A
Anim.Page({
// ...省略部分代码
handleNavigateTo(){
wx.navigateTo({
url: '/pages/permission/index'
})
}
})
// pages/b.js
// 页面 B
Anim.Page({
// ...省略部分代码
handleNavigateTo(){
// 页面 B 的专属业务逻辑
if(this.data.BData === 'something'){
wx.showModal({
title: '温馨提示',
content: 'BData 为 something',
showCancel: false,
});
} else {
wx.navigateTo({
url: '/pages/permission/index'
})
}
}
})
业务代码的复杂度通过上面比对,可以看到,采用路由守卫能力后,业务代码的复杂度大大降低,更易于开发者进行维护。实际上我们把代码复杂度,都隐藏到了 Anim.interceptors.router
中。接下来我们看看 Anim.interceptors.router
的具体配置。
const userStore = require('../store/userStore.js');
// 需要状态检测的页面列表
const needLogin = ['/pages/permission/index'];
const needSelected = ['/pages/permission/index'];
Anim.interceptors.router({
beforeEach(to, from) {
// 命中了 needLogin 页面,则需要判断登录态
if(needLogin.includes(to.url) && !userStore.isLogin()){
return {
url: '/pages/permission/no-permission'
}
}
// 命中了 needSelected 页面,则需要判断是否已经有一个全局选择状态
if(needSelected.includes(to.url) && !getApp().globalData.isSelected){
return {
url: '/pages/permission/no-selected'
}
}
},
})
整个路由守卫的入口是 Anim.interceptors.router
,然后通过 beforeEach
钩子来实现路由跳转前的逻辑。在这个钩子中,我们可以通过 to
和 from
来获取当前路由和上一个路由的信息,然后通过 return
来控制路由跳转的行为。靠这个我们就可以去定义我们的 login / selected 这类需要全局判断的数据了。
快点在你的项目里试试 Anim.interceptors.router
吧!