主题
路由拦截
在小程序中,需要做类似后台页面的访问权限的拦截,防止用户直接访问某些页面。一般情况下,分登录可访问和非登录可访问的页面。一般可以这么做,例如登录页面,需要在非登录情况下才可以访问。就会有下面的代码
ts
import { useUserStore } from '@/store/user'
// 从 store 中获取当前登录的用户信息
const userStore = useUserStore()
// 如果用户登录直接跳转到用户中心页面
if (userStore.isLogined) {
toUserCenter()
}
如果页面不多的情况,硬编码的话其实还能接受,如果是大量页面,这样的代码就会重复很多,而且维护起来非常麻烦。如果页面不光是这种简单认证权限,还有更复杂的权限控制,比如需要根据用户的角色来决定是否可以访问某个页面,那么就需要使用路由拦截器来实现。
找到对应的路由文件 interceptors\route.ts
ts
import { useUserStore } from '@/store'
import { getNeedLoginPages, needLoginPages as _needLoginPages } from '@/utils'
// TODO Check
const loginRoute = '/pages/login/index'
const isLogined = () => {
const userStore = useUserStore()
return userStore.isLogined
}
const isDev = import.meta.env.DEV
// 黑名单登录拦截器 - (适用于大部分页面不需要登录,少部分页面需要登录)
const navigateToInterceptor = {
// 注意,这里的url是 '/' 开头的,如 '/pages/index/index',跟 'pages.json' 里面的 path 不同
invoke({ url }: { url: string }) {
console.log(url) // /pages/route-interceptor/index?name=feige&age=30
const path = url.split('?')[0]
let needLoginPages: string[] = []
// 为了防止开发时出现BUG,这里每次都获取一下。生产环境可以移到函数外,性能更好
if (isDev) {
// 重点这里获取需要登录的页面,找到 getNeedLoginPages() 方法
needLoginPages = getNeedLoginPages()
} else {
needLoginPages = _needLoginPages
}
console.log(needLoginPages.includes(path))
if (needLoginPages.includes(path)) {
const isLogin = isLogined()
if (isLogin) {
return true
}
const redirectRoute = `${loginRoute}?redirect=${encodeURIComponent(url)}`
uni.navigateTo({ url: redirectRoute })
return false
}
return true
}
}
ts
export const getAllPages = (key = 'needLogin') => {
const pages = [
...pagesJson.pages
// 最终在这里
// page 设置的时候需要加上 `needLogin` key
.filter((page) => !key || page[key])
.map((page) => ({
...page,
path: `/${page.path}`
}))
]
...
}
配置
找到跟目录的 pages.json
文件,在 pages.json
文件中找到如下的配置
json
{
"pages": [
{
"path": "pages/index/index",
"type": "home",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "首页"
}
},
{
"path": "pages/login/index",
"type": "page",
"layout": "default"
},
{
"path": "pages/user/index",
"type": "page",
"needLogin": true, // 添加需要登录的标记即可
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "我的"
}
}
]
}