这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战
继续上一章的动态路由,下面展示核心部分的js内容:
一、过滤用户只能展示的路由部分
store部分实现持久化数据并生成新的路由表
utils/filterPermissionRoutes.js
这个过滤路由的js主要是通过所有动态路由表里设置的title标题和用户只有权限的标题名称进行过滤,这里多设置了menu_id用来增加字段因为后面会用到这个menuid去查询每个页面有哪些按钮权限,这里还用到递归进行子菜单的循环继续过滤。
export const filterPermissionRoutes = ( allPermissionRoutes = [], userPermissionRoutes = []) => { const renderRoutes = [] allPermissionRoutes.forEach(allItem => { userPermissionRoutes.forEach(userItem => { if (!allItem.meta) { renderRoutes.push(allItem) return } if (userItem.title === allItem.meta.title) { allItem.menu_id = userItem.menu_id; allItem.jump = userItem.jump; if (userItem.list && userItem.list.length > 0) { allItem.children = filterPermissionRoutes( allItem.children, userItem.list ) } renderRoutes.push(allItem) } }) }) return renderRoutes}// 设置默认显示菜单export const setRedirect = routes => { routes.forEach(item => { if (item.children && item.children.length > 0) { item.redirect = { name: item.children[0].name } setRedirect(item.children) } })}
utils/generateRoutes.js
这个主要是把所有路由进行过滤然后重新封装,通过上面的js进行过滤菜单然后重定向返回新的路由出去。
import { allPermissionRoutes } from '../router/allPermissionRoutes'import { dynamicRoutes } from '../router/dynamicRoutes'import { filterPermissionRoutes, setRedirect } from './filterPermissionRoutes'export const generateRoutes = userPermissionRoutes => { const menuRoutes = filterPermissionRoutes( dynamicRoutes, userPermissionRoutes ) const containerRouter = allPermissionRoutes.find(r => r.path === '') containerRouter.children.push(...menuRoutes) // set redirect setRedirect(allPermissionRoutes) return [menuRoutes, allPermissionRoutes]}
store/index.js
数据存储管理器的主要功能就是存储当前用户只能展示的路由数组,并在登录的时候把接口返回的用户菜单数组和本地所有菜单数组进行过滤,生成新的路由表持久化数据,然后存到localStorage里,进行全局管理并缓存路由,方便后期token没过期的时候直接拿取(一般只要浏览器不刷新清缓存就不会有问题啥的)。
import Vue from 'vue'import Vuex from 'vuex'import router from '../router'import { generateRoutes } from '../utils/generateRoutes'Vue.use(Vuex)export default new Vuex.Store({ state: { menuRoutes: [] }, mutations: { SET_MENUS: (state, menus) => { state.menuRoutes = menus }, CLEAR_MENUS: state => { state.menuRoutes = [] } }, actions: { // eslint-disable-next-line no-unused-vars async login({ commit }, loginForm) { const { userName,headImg,token, authorityList} = loginForm; // 持久化数据 localStorage.setItem('TOKEN', token) localStorage.setItem('USER_INFO', JSON.stringify({ userName, headImg, authorityList })) }, async getMenu({ commit }) { const { authorityList } = JSON.parse(localStorage.getItem('USER_INFO')) const [menuListRoutes, dynamicRoutes] = generateRoutes(authorityList) const realRoutes = [...router.options.routes, ...dynamicRoutes] // 生成新的路由表 router.addRoute(...realRoutes) commit('SET_MENUS', menuListRoutes) } }})
二、内容组件动态展示
components/MContent.vue
因为这个内容组件中的router-view是基本的动态组件,所以这里用到了vue的单个路由过渡动效,用来只改变中间内容部分有一个过渡的效果。
<template> <section style="height: 100%"> <transition name="fade" mode="out-in"> <router-view></router-view> </transition> </section></template><script>export default { name: "AppMain",};</script>
最后一定要记得在退出登录的时候进行全局变量卸载,路由清空,并且重定向路由地址,不然会出现死循环报错等问题。
loginOut:
localStorage.clear();
window.location.reload();
三、最后疑问
如果深入到按钮都是动态展示的,并且每跳转一个页面,都要查询当前页面按钮有哪些,该怎么做呢?
感谢阅读,有问题可以留言提问~