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的写法也不一样

  • 3
    点赞
  • 8
    收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论 4

打赏作者

有衡

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值