Skip to content

路由拦截

在小程序中,需要做类似后台页面的访问权限的拦截,防止用户直接访问某些页面。一般情况下,分登录可访问和非登录可访问的页面。一般可以这么做,例如登录页面,需要在非登录情况下才可以访问。就会有下面的代码

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": "我的"
      }
    }
  ]
}