Skip to content
On this page

利用路由守卫控制入口权限

在实际研发过程中,会有很多页面需要控制权限,比如只有登录用户才能访问的页面,或者只有管理员才能访问的页面。这些都可以通过路由守卫来实现。Anim 框架提供了路由守卫的功能,可以很方便的实现这些功能。我们来看看在最佳实践场景下,该如何使用路由守卫能力。

页面权限控制

下面我们看一下模版中的例子

原本是跳转到 /pages/permission/redirect

image-20230403162225195

实际上被 Anim Router 重定向到了 /page/permission/index

image-20230403162458196

而未登录展示模态框,在未登录时点击,则会出现事先配置好的模态框。

image-20230403162600978

路由守卫的优势

可以看到,我们在实际上的业务代码中,并没有对与特定的路由进行业务逻辑的检测。这使得我们的业务逻辑非常的干净,只需要关注正常情况下,这个路由要跳转到什么地方。这样我们可以从复杂的业务流程代码中解放开,不同的页面在进行该路由跳转时,都无需再重复判断跳转逻辑。而且最重要的一点是,我们可以避免忘记写跳转逻辑导致页面被错误打开,因为该跳转逻辑是基于最底层的 wx.navigateTowx.redirectTo

对有需要在路由跳转前做全局的前置业务逻辑判断的,都可以采用这类代码模式。在实际业务过程中,可能会采用业务状态 + 全局状态的混合使用方式,来达到最佳的效果。

代码比对

在实际业务下,当我们遇到了业务状态+全局状态需要进行逻辑判断后进行路由跳转时。

我们的需求如下:

  1. 当我们未登录时,跳转到 /pages/permission/no-permission
  2. 当我们全局数据中的 isSelectedfalse 时,跳转到 /pages/permission/no-selected
  3. 如果都正常,则跳转到 /pages/permission/index
  4. 页面 B 中,大部分逻辑如上,但是包含自己一个特殊的逻辑,当 BDatasomething 时,则需要弹出模态框不做跳转。

⚠️未采用路由守卫能力

不同页面进行逻辑跳转时,都会加入大量的业务代码进行判断。虽然我们可以进行逻辑封装,一定程度缓解这个事情。但是如果遇到其他同学忘记了使用该封装的方法,就会导致页面被错误打开。

js
// 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'
      })
    }
  }
})

另一个页面仍然要包含相同的逻辑判断,甚至可能会出现判断逻辑遗漏的情况。

js

// 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'
      })
    }
  }
})

✅采用路由守卫能力

js
// pages/a.js
// 页面 A
Anim.Page({
  // ...省略部分代码
  handleNavigateTo(){
    wx.navigateTo({
      url: '/pages/permission/index'
    })
  }
})
js
// 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 的具体配置。

js
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 钩子来实现路由跳转前的逻辑。在这个钩子中,我们可以通过 tofrom 来获取当前路由和上一个路由的信息,然后通过 return 来控制路由跳转的行为。靠这个我们就可以去定义我们的 login / selected 这类需要全局判断的数据了。

快点在你的项目里试试 Anim.interceptors.router 吧!

Released under the MIT License.