0


(二) Vue3 + Element-Plus 实现动态菜单栏

系列文章目录

  1. 系列介绍:Vue3 + Vite + TS 从零开始学习
  2. 项目搭建:(一) Vue3 + Vite + TS 项目搭建
  3. 实现动态菜单栏:(二) Vue3 + Element-Plus 实现动态菜单栏
  4. 实现动态面包屑:(三) Vue3 + Element-Plus 实现动态面包屑
  5. 实现动态标签页:(四) Vue3 + Element-Plus 实现动态标签页
  6. 实现动态主题色切换(demo):(五) Vue3 + Element-Plus 实现动态主题色切换
  7. 踩坑记录(持续更新):(六) Vue3 踩坑记录

文章目录


一、引入依赖

开始前请确保已经安装以下依赖:

  1. VueX
$ npm i vuex --save
  1. Vue-Router
$ npm i vue-router --save
  1. NProgress
$ npm i nprogress --save

二、目录结构

|-src                   -- 主目录
---|api                 -- Ajax请求统一存放目录
------|auth-api.js      -- 路由数据获取接口
---|js                  --JS脚本
------|permission.js    -- NProgress进度条数据处理
---|layout              -- 页面布局组件
------|sidebar.vue      -- 侧边栏布局组件
---|store               -- VueX
------|router.js        -- 路由全局常量

三、核心代码

1. auth-api.js

import request from'@/js/request'exportdefault{routers(data){return request.post('/routers', data)}}

2. permission.js

import router from'../router'import store from'../store'import NProgress from'nprogress'import'nprogress/nprogress.css'import{ getCookie }from'./cookie'import Layout from'../layout/index.vue'import ParentView from'../components/ParentView/index.vue'

NProgress.configure({showSpinner:false})const whiteList =['/login','/register']

router.beforeEach((to, from, next)=>{
  NProgress.start()if(getCookie()){if(to.path ==='/login'){next({path:'/'})
      NProgress.done()}else{if(store.state.user.menus.length ===0){
        store.dispatch('GetInfo').then(res=>{const menuIds = res.data.menuIds
          store.dispatch('GenerateRoutes', menuIds).then(routes=>{filterRoutes(routes)
            routes.forEach(route=>{
              router.addRoute(route)})next({...to,replace:true})})}).catch(()=>{next()})}else{next()}}}else{if(whiteList.indexOf(to.path)!==-1){next()}else{next(`/login?redirect=${to.fullPath}`)
      NProgress.done()}}})

router.afterEach(()=>{
  NProgress.done()})constfilterRoutes=(routes)=>{const accessRoutes = routes.filter(route=>{let modules =import.meta.glob('../views/**/*.vue')if(route.component){if(route.component ==='ParentView'){
        route.component = ParentView
      }elseif(route.component ==='Layout'){
        route.component = Layout
      }else{
        route.component = modules[`../views/${route.component}.vue`]}}if(route.children && route.children.length){filterRoutes(route.children)}returntrue})return accessRoutes
}

3.sidebar.vue

<template><el-aside width="210px"class="aside-wrapper"><el-scrollbar><el-menu :default-active="route.path" mode="vertical":collapse-transition="false" router class="menu-wrapper"><el-sub-menu v-for="menu in menus":key="menu.path":index="menu.path"><template #title><el-icon><component :is="menu.meta.icon"/></el-icon><span>{{ menu.name }}</span></template><el-menu-item v-for="child in menu.children":key="child.path":index="child.path"><template #title><el-icon><component :is="child.meta.icon"/></el-icon><span>{{ child.name }}</span></template></el-menu-item></el-sub-menu></el-menu></el-scrollbar></el-aside></template><script lang="ts" setup>import{ computed }from'vue'import{ useStore }from'vuex'import{ useRoute }from'vue-router'const store =useStore()const route =useRoute()const menus = store.state.router.accessRoutes

</script>

4.router.js

import{ authApi }from'@/api'import constantRoutes from'@/router/routes'const router ={state:{routes:[],accessRoutes:[]},mutations:{SET_ROUTES:(state, routes)=>{
      state.routes = routes
    },SET_ACCESSROUTES:(state, accessRoutes)=>{
      state.accessRoutes = accessRoutes
    }},actions:{GenerateRoutes({ commit }, roleIds){returnnewPromise(resolve=>{
        authApi.routers(roleIds).then(res=>{const accessRoutes = res.data
          filterRoutes('', accessRoutes)const routes = constantRoutes.concat(accessRoutes)commit('SET_ROUTES', routes)commit('SET_ACCESSROUTES', accessRoutes)resolve(routes)})})}}}constfilterRoutes=(path, routes)=>{
  routes.forEach(route=>{const routePath = route.path
    if(route.parentId !=='0'){
      route.path = path +"/"+ routePath
    }if(route.children && route.children.length){filterRoutes(routePath, route.children)}})}exportdefault router

四、最终效果

效果图


本文转载自: https://blog.csdn.net/Bao59/article/details/128763826
版权归原作者 下辈子不当程序猿 所有, 如有侵权,请联系我们删除。

“(二) Vue3 + Element-Plus 实现动态菜单栏”的评论:

还没有评论