本文已参与[新人创作礼]活动,一起开启掘金创作之路
1. 目的
删除前端项目多余页面以及路由配置定义的路由定义
2. 背景
在项目中,我们要实现的最终效果是,不同用户登录进来显示出的是不同的菜单
3. 理解
(1)静态路由表
不需要做权限控制的路由,每个用户都可以访问
(2)动态路由表
需要做权限控制的路由,用户如果权限不一致,访问到的路由也不一样
4. 工作原理
用户登录之后,根据其携带的权限不同动态生成路由配置
5. 拆分静态和动态路由表
进入router/index.js文件
1.补充一个动态路由表asyncRoutes
2.将动态和静态合并在一起
注意:静态路由我们已经具备,接下来只需要生成动态路由,为了方便做权限控制,我们可以先将动态路由全部显示出来,后面我们会进行权限控制
// 静态路由表,项目中每个用户都可以访问
export const constantRoutes = [
//省略
]
// 动态路由表,项目中不同的用户可以访问不同的功能
export const asyncRoutes = [
//暂略
]
const createRouter = () => new Router({
// 控制路由滚动行为,滚动到顶部
scrollBehavior: () => ({ y: 0 }),
// 组合到一起组成路由表
routes: [...constantRoutes, ...asyncRoutes]
})
6. 设置路由
补充路由配置
export const asyncRoutes =[ {
path: '命名',
name: '命名',
component: () => import(相对路径),
meta: {数据}
}
]
在router文件中将它们设置为layout组件的二级路由
{
path: '在@/layout的路径',
component: Layout(组件),
children: [{
path: '', // 这里当二级路由的path什么都不写的时候表示当前路由为默认路由直接渲染对应组件
name: '命名',//给路由规则命名
component: () => import('相对路径'),
meta: { 数据 }
}]
}
小结 要想把所有功能都包含在layout中,需要将他们设置为layout的子路由
7. 后续问题
随着我们开发的项目越来越大,功能越来越复杂时,我们需要动态管理的路由数量也会越多,那我们的router/index.js文件会变得越大,不利于维护
目标
对router.js路由中的动态路由进行物理目录拆分,实现模块化管理
思路
将每一个路由配置在单独的文件中,然后统一导入使用
8. 创建文件
在views目录下执行指令
mkdir xxx xxx xxx xxx
此指令为Linux操作系统下的,Window用不了,此时我们在git下执行即可
9. 文件内容
import Layout from '@/layout'
export default {
path: '@/layout下的路径',
component: Layout(组件),
children: [{
path: '', // 这里当二级路由的path什么都不写的时候表示当前路由为默认路由直接渲染对应组件
name: '命名',//给路由规则命名
component: () => import('相对路径'),
meta: { 路由原信息 }//存储数据的对象
}]
}
10. router/index.js
/* Layout */
import Layout from '@/layout'
import Router from './modules/xxx'
import Router from './modules/xxx'
import Router from './modules/xxx'
import Router from './modules/xxx'
// 动态路由表,项目中不同的用户可以访问不同的功能
export const asyncRoutes = [
Router,
Router,
Router,
Router,
]
const createRouter = () => new Router({
// 控制路由滚动行为,如果出现滚动切换就让页面返回顶部
scrollBehavior: () => ({ y: 0 }),
// 临时组合到一起组成路由表
routes: [...constantRoutes, ...asyncRoutes]//下面筛选权限要将...asyncRoutes省略
})
小结: 将路由拆分到不同文件中,这样可以使让我们更快地“对症下药”
11. 路由表数据处理
1.this.$router.options.routes 可以拿到完整的路由表数据
12. 权限应用--动态生成左侧菜单
分析
(1)登录成功(页面跳转),进入导航守卫:
(1)1 获取个人权限信息(使用员工账号登录,查看个人信息接口)
(2)2 生成可以访问的动态路由(之前掘金有写这里就不细说了)
router/index.js
const createRouter = () => new Router({
// mode: 'history', // require service support,去#
scrollBehavior: () => ({ y: 0 }),
// routes: [...constantRoutes, ...asyncRoutes]
routes: [...constantRoutes]
})
permission.js
// 表示之前没有获取用户信息==第一次登录进来==需要获取用户信息
// 获取用户信息
// await store.dispatch('user/getInfo')
const {
data: {
roles: { menus }
}
} = await store.dispatch('user/getInfo')
// 深层解构menus
// console.log(menus, asyncRoutes, 7555)
/* 1-根据获取的权限筛选出对应的路由匹配规则 */
var filterRouter = asyncRoutes.filter((item) => {
// 筛选不需要的动态路径
var name = item.children[0].name
// 获取子路径名称
var flag = menus.includes(name)
// 判断权限中是否包含该路径名
if (flag) {
return item
}
})
/* 2-动态添加路由匹配规则 */
router.addRoutes(filterRouter)
/* 3-将动态路由传入store中 */
store.commit('menu/serRoutes', filterRouter)
}
(2)在vuex中保存菜单数据
(2)1.创建store/module/menu.js用于存储路由
import { constantRoutes } from '@/router'
export default {
state() {
return {
routes: []
}
},
mutations: {
serRoutes(state, route) {
state.routes = [...constantRoutes, ...route]
}
},
actions: {},
getters: {},
namespaced: true
}
(2)2 在store/index.js中挂载menu.js
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import app from './modules/app'
import settings from './modules/settings'
import user from './modules/user'
+ import menu from './modules/menu'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
app,
settings,
user,
+ menu
},
getters
})
export default store
(2)3 在左侧菜单栏显示文件src\layout\components\Sidebar\index.vue中进行渲染
<sidebar-item
- v-for="route in routes"
+ v-for="route in $store.state.menu.routes"
:key="route.path"
:item="route"
:base-path="route.path"
/>
效果如下
总结:使用权限数据做过滤处理
bug处理
刷新页面时的`bug`修复
问题
(1)如果我们刷新浏览器,会发现跳到了404页面
(2)对于addRoute添加的路由,再刷新时会白屏
原因
刷新浏览器,会发现跳到了`404`页面
现在我们的路由设置中的`404`页处在中间位置而不是所有路由的末尾了。
解决
(1)404bug:
注意:记得在router/index文件中删除404
permisson.js
router.beforeEach(async(to, from, next) => {
... ...
filterRouter.push({ path: '*', redirect: '/404', hidden: true })
(2)解决刷新出现的白屏bug:动态路由没有及时获取
permisson.js
router.beforeEach(async(to, from, next) => {
... ...
// 白屏 因为路径是后加进去的,刷新会返回到最初的页面才白屏,
// 所以需要重定向到后加路径后的当前页面
// path: to.path可写成to path,replace: true可省略
//可写成 next(to.path)
next({ path: to.path, replace: true })
退出登录时重置路由
问题
退出后,再次登陆,发现菜单异常 (控制台有输出说路由重复);
原因
路由设置是通过router.addRoutes(filterRoutes)来添加的,退出时,并没有清空,再次登陆,又加了一次,所以有重复。
思路
需要将路由权限重置 (恢复默认) 将来登录后再次追加才可以,不然的话,就会重复添加
router中记录两次公共路由,第一次用于正常操作,第二种用于重置路由,重置路由在登录事件触发时调用
router/index.js
const router = createRouter()
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher // reset router
}