Vue3中的动态路由
vue
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
项目地址:https://gitcode.com/gh_mirrors/vu/vue
·
前言
最近在用vue3及相关生态完成自己一个小的博客网站搭建来学习时,想到以前开发中遇到菜单生成是由后端返回数据动态生成的,但是这块逻辑不是自己写的,所以理解不深刻。趁着这次学习vue3时准备实操一波。
一、用户权限和菜单列表数据
在store文件夹下新建menu.ts文件,引入pinia(vue3推荐的全局存储,和vuex类似)创建store存储菜单数据以及定义生成动态路由的方法,通过addRoute添加动态路由
import { ref, reactive, computed } from 'vue'
import { defineStore } from 'pinia'
import type { TSideMenu } from '@/type'
import router from '../router/index'
import {compMoudles} from '@/router/compModule'
export const useMenuStore = defineStore('Menu', () => {
// 返回的菜单数据
let rootMenu = ref([] as TSideMenu[])
// 侧边栏菜单数据
let sideMenu = ref([] as TSideMenu[])
function setRootMenu(menu:TSideMenu[]) {
rootMenu.value = menu
addRouters(menu)
if(rootMenu.value.length>0){
sideMenu.value = rootMenu.value[0].children
}
}
function addRouters(menu:TSideMenu[]){
for (let index = 0; index < menu.length; index++) {
let menuItem = menu[index];
if(menuItem.children.length>0){
addRouters(menuItem.children)
}else{
console.log(menuItem,'menuItem')
router.addRoute("Home",
{ path: menuItem.menuUrlParam?`${menuItem.menuUrl}${menuItem.menuUrlParam}`:menuItem.menuUrl as string,
component: compMoudles[menuItem.menuCode],
children: [],
})
}
}
}
function setSideMenu(menu:TSideMenu[]) {
sideMenu.value = [...menu]
}
return { sideMenu,rootMenu, setRootMenu,setSideMenu}
})
二、设置动态路由
1.在router下新建compModule.ts
该文件中定义动态路由对应的vue文件。在addRouter中添加component时根据menuCode引入
export const compMoudles = {
kweichowMt:()=>import('../views/personCenter/myCollection.vue'),
vueBlog:()=>import('../views/article/index.vue'),
addBlog:()=>import('../views/article/addBlog.vue'),
blogList:()=>import('../views/article/blogList.vue')
}
2.在router下新建index.ts文件
在index.ts中定义默认的静态路由以及全局路由守卫做鉴权处理,我这里还有相关功能需完善。
import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router'
import LoginView from '../views/login/index.vue'
import MainIndex from '@/views/mainIndex/index.vue'
import layout from '@/views/layout/index.vue'
import {useUserStore} from '@/stores/user'
import { useMenuStore } from '@/stores/menu'
import {getMenuByRole} from './routerUtils'
const baseRoutes = [
{
path: '/login',
name: 'login',
component: LoginView
},
{
path: '/',
component: layout,
redict:'/home',
name:'Home',
children: [
{ path: "/home", component: MainIndex, name:'MainIndex',
meta:{
title:'首页'
}
},
],
},
]
const router = createRouter({
history: createWebHashHistory(),
routes: baseRoutes,
scrollBehavior (to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return { top: 0 }
}
}
})
router.beforeEach(async(to, from) => {
const ustore = useUserStore()
const mstore = useMenuStore()
// 未登陆跳转到登陆页 store的局限性 刷新后丢失存储
if(to.path =='/login'){
return true
}
if(!ustore.token && to.path!='/login'){
return '/login'
} else {
// debugger
// 已登录已加载菜单 直接next
if(mstore.rootMenu.length>0) {
return true
} else {
//已登录未加载菜单 根据角色请求菜单
const res= await getMenuByRole(ustore.userRole)
if(res){
// 动态注册路由
mstore.setRootMenu(res.data.resultList)
}
return to.fullPath
}
}
})
export default router
因为vueRouter的路由守卫不推荐next,所以我使用return,但是在该处一开始我是将return放在异步函数的回调中,造成页面刷新一直白屏,才恍然大悟,return一定要在路由守卫的函数中,但是要保证动态路由已生成,所以使用await,在外层使用return进行重定向即可。
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:2 个月前 )
9e887079
[skip ci] 1 年前
73486cb5
* chore: fix link broken
Signed-off-by: snoppy <michaleli@foxmail.com>
* Update packages/template-compiler/README.md [skip ci]
---------
Signed-off-by: snoppy <michaleli@foxmail.com>
Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 1 年前
新一代开源开发者平台 GitCode,通过集成代码托管服务、代码仓库以及可信赖的开源组件库,让开发者可以在云端进行代码托管和开发。旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。
更多推荐


所有评论(0)