Vue3中的动态路由

前言

         最近在用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进行重定向即可。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值