关于VUE 前端路由过滤器的想法和实现

1. 路由过滤器想法

路由过滤器的想法来源于后台的过滤器想法,后台会将到前端发起的一个个的请求,进入到一个个的过滤器中,只有当过滤器中的一些比如是否登录、是否具有相关权限的校验通过后,才会放行这个过滤器。对于前端来说,所有的路由都需要经过router.beforeEach这个统一的路由拦截方法,我想在前端通过像后端编写过滤器的方式,来对前端路由做一定的控制。
这样做一个是能够简化代码,让代码逻辑更加清晰易懂,不会出现逻辑混合在一起的情况,再有就是可以职责分离,每一个过滤器都只负责自己需要校验的功能。最后是便于追踪,可以清楚的知道页面是在那一个过滤器中出现的问题,便于调试和定位代码。

2. 路由过滤器的实现

  1. 我首先定义了一个统一的过滤器类,通过继承和复写的方式来实现过滤器子类。这也是面向对象通常使用的方式吧,虽然js好的实现方式可能是组合而非继承
export default class BaseFilter {
  // 主要的过滤器方法
  async filter(to, from) {
  }
  // 过滤器名字
  getName() {
    throw new Error('必须要覆写此方法')
  }
  // 过滤器排序
  order() {
    return 1
  }
}

  1. 通过实现判断用户是否登录,如果用户未登录则跳转首页的过滤器
import BaseFilter from './baseFilter'

export default class LoginFilter extends BaseFilter {
  async filter(to, from) {
    // 判断路由是否需要校验登录
    if (!to.meta.requireLogin) {
      return null
    }
    // 如果用户未登录则直接返回一个新的路由地址,跳转首页
    if (store.state.user.isLogin !== true) {
      return {
        path: '/',
        query: { referrer: to.fullPath  }
      }
    }
  }
  getName() {
    return 'LoginFilter'
  }
}

  1. 通过返回一个filterHandler方法来组合实现路由过滤
const files = require.context('.', false, /\.js$/)
// 过滤器实例化类数组
const ORIGINAL_FILTER_LIST = []
// 导入所有过滤器
files.keys().forEach(key => {
  if (key === './index.js' || key === './baseFilter.js') return
  const Clazz = files(key).default
  ORIGINAL_FILTER_LIST.push(new Clazz())
})
// 依次校验过滤器
export default async function filterHandler(to, from) {
  // 调整过滤器先后顺序
  ORIGINAL_FILTER_LIST = ORIGINAL_FILTER_LIST.sort((a, b) => {
    return b.order() - a.order()
  })
  let handlerResult = null
  let lastIndex = 99999
  console.groupCollapsed('路由FILTER')
  console.log('------------------------ FILTER START ------------------------')
  for (let i = 0; i < ORIGINAL_FILTER_LIST.length; i++) {
    const filterChainListElement = ORIGINAL_FILTER_LIST[i]
    const filterResult = await filterChainListElement.filter(to, from)
    if (handlerResult == null && filterResult != null) {
      handlerResult = filterResult
      lastIndex = i
    }
    if (i < lastIndex) {
      console.log('- ' + ORIGINAL_FILTER_LIST[i].getName() + '%c [通过]', 'color:#0f0;')
    } else if (i === lastIndex) {
      console.log('- ' + ORIGINAL_FILTER_LIST[i].getName() + '%c [失败]', 'color:#f00;')
    } else {
      console.log('- ' + ORIGINAL_FILTER_LIST[i].getName() + '%c [未进入]', 'color:#abc;')
    }
  }
  console.log('------------------------ FILTER END ------------------------')
  console.groupEnd()
  return handlerResult
}
  1. 最后在router.beforeEach中调用filterHandler
import filterHandler from './filter'
router.beforeEach(async(to, from, next) => {
  const filterResult = await filterHandler(to, from, next, filterList)
    if (filterResult != null) {
      next(filterResult)
    } else {
      next()
    }
})

这样路由过滤器的改造就完成了


image.png

你可能感兴趣的:(关于VUE 前端路由过滤器的想法和实现)