vue3 +vite 动态菜单和路由懒加载

当前项目是根据vue-element-admin使用vite+vue3重构的后台管理系统

从后台获取动态菜单并且路由懒加载

后台返回的数据结构


  "code": 0,
  "msg": "成功",
  "data": [
    {
      "path": "/administrator",
      "meta": {
        "title": "后台管理",
        "icon": "icon-a-zu4",
        "roles": [
          "admin"
        ]
      },
      "children": [
        {
          "path": "admin",
          "meta": {
            "title": "管理员",
            "roles": [
              "admin"
            ]
          },
          "component": "views/administrator/admin"
        },
        {
          "path": "role",
          "meta": {
            "title": "角色",
            "roles": [
              "admin"
            ]
          },
          "component": "views/administrator/role"
        },
        {
          "path": "auth",
          "meta": {
            "title": "权限",
            "roles": [
              "admin"
            ]
          },
          "component": "views/administrator/auth"
        }
      ],
      "component": "Layout",
      "redirect": "/administrator/admin",
      "alwaysShow": true
    }
  ]
}

src/permission.js请求菜单信息

const accessRoutes = await store.dispatch('permission/generateRoutes') // 获取当前用户的菜单信息

store/modules/permission.js将之前的前端写死的路由改成去后台请求对应的菜单

const actions = {
    generateRoutes({ commit }) {
        return new Promise(resolve => {
            menu({username: storage.getItem('username')}).then((response) => {
                let accessedRoutes = filterAsyncRoutes(response.data)
                commit('SET_ROUTES', accessedRoutes)
                resolve(accessedRoutes)
            })
        })
    }
}

store/modules/permission.js添加地址 菜单过滤 生成对应的菜单

export function filterAsyncRoutes(routes) {
    const async = routes.filter(route => {
        if(route.component){
            route.component = Layout
            if(route.children && route.children.length){
                route.children.forEach(item => {
                    item.component = loadView(item.component)
                })
                return true
            }
            return true
        }
        return true
    })
    console.log(async)
    return async
}

/**
 * 路由懒加载 拼接
 * @param view
 * @returns {function(): *}
 */
export const loadView = (view) => {
	// 这里需要注意一下 vite+vue3 要用 defineAsyncComponent 才能拼接成功 不然会一直报错找不到模块  加上/* @vite-ignore */ 可以不显示警告
    return () => defineAsyncComponent(() => import(/* @vite-ignore */`/src/${view}.vue`))
}

store/modules/permission.js将不需要权限的路由过滤

const mutations = {
    SET_ROUTES: (state, routes) => {
        state.addRoutes = routes
        // 过滤掉不需要显示在菜单栏的公共菜单 并格式化
        let constant = filterConstantRoutes(constantRoutes)
        state.routes = constant.concat(routes)
    }
}

/**
 * 过滤递归公共路由
 * @param routes
 * @returns {*[]}
 */
export function filterConstantRoutes(routes){
    const router = routes.filter( item => !item.hidden )
    const routeList = []
    for (const item of router) {
        let temp = {}
        if (!item.alwaysShow && item.children.length) {
            temp.path = item.path
            temp.meta = item.children[0].meta
            temp.alwaysShow = false
            routeList.push(temp)
        } else {
            routeList.push(item)
        }
    }
    return routeList
}

直接在菜单界面遍历出来就可以显示成功
在这里插入图片描述
注意:后台的数据结构,不要写错了

loadView 的地方很容易搞错,vue2和vue3的写法是不一样,js和ts的写法也不一样
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值