美文网首页
vue2 el-menu 动态路由配置

vue2 el-menu 动态路由配置

作者: 苏苡 | 来源:发表于2023-12-14 10:13 被阅读0次
    1. 登陆后APP.vue数据获取并存储
    <template>
      <div id="app">
        <router-view />
      </div>
    </template>
    
    <script>
    export default {
      name: 'App',
      data() {
        return {}
      },
      // 检测router变化后更新数据
      watch: {
        $route: {
          async handler(newVal) {
            this.getMenuData()
          }
        }
      },
      created() {},
      methods: {
        // 菜单管理
        async getMenuData() {
          await this.$http.post('菜单树据获取API', {'参数'}).then(res => {
            if (res.status != -1) {
              const { result} = res;
              result.forEach(i => {
                let arr = []
                result.forEach(s => {
                // 同级平铺数据的处理,需要请参考 不需要直接存store即可
                  if(i.menuId === s.parentId) { // 判断数据是否包含了子数据
                    arr.push(s) // 存储子数据
                    this.$set(i, 'children', arr) // set到对应的父级数据中
                  }
                })
              })
              let arrData = []
              // 过滤子集数据
              result.forEach((i, index) => {
                if(!i.parentId) {
                  arrData.push(i)
                }
              })
              // 处理完成后存储到store
              this.$store.commit('MENU_LIST', JSON.stringify(arrData))
              localStorage.setItem("MENU_LIST", JSON.stringify(arrData))
            }
          })
        },
      }
    }
    </script>
    
    2. store index.js文件配置

    localStorage.getItem('MENU_LIST') 为了刷新页面不丢失数据

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    const store = new Vuex.Store({
      state: {
        menuIds: localStorage.getItem('MENU_LIST') || []
      },
      mutations: {
        // 存储数据源
        MENU_LIST(state, id) {
          state.menuIds = id;
          localStorage.setItem('MENU_LIST', id)
        }
      },
      actions: {}
    })
    
    export default store
    
    3. 父组件 菜单树
    // 设置router 为了子组件:index="item.path" 绑定做跳转页面
    <template>
      <div>
        <el-scrollbar wrap-class="scrollbar-wrapper">
          <el-menu
            router
            :default-active="activeMenu"
            :collapse="isCollapse"
            :background-color="variables.menuBg"
            :text-color="variables.menuText"
            :unique-opened="false"
            :active-text-color="variables.menuActiveText"
            :collapse-transition="false"
            mode="vertical"
          >
            <sidebar-item
              v-for="(route,index) in JSON.parse(menuIds)" 
              :key="index"
              :item="route"
              :base-path="route.path"
            />
          </el-menu>
        </el-scrollbar>
      </div>
    </template>
    
    <script>
    import SidebarItem from './SidebarItem'
    export default {
      data() {
        return {}
      },
      computed: {
        ...mapState(['menuIds']),  // 数据来源store
        activeMenu() {  // 为了在路由切菜单的时候选中左侧菜单树
          const route = this.$route
          const { path } = route
          return path
        },
        left() {
          return this.sidebar.opened ? 'flex-start' : 'center'
        },
        variables() {
          return variables
        },
        isCollapse() {
          return !this.sidebar.opened
        }
      }
    }
    </script>
    
    4. 子组件
    <template>
      <div>
        <el-menu-item v-if="!item.children || item.children.length <= 1" :index="item.path">
          <item :icon="item.icon" :title="item.menuName"/>
        </el-menu-item>
        <el-submenu v-else ref="subMenu" popper-append-to-body :index="item.path">
          <template slot="title">
            <item :icon="item.icon" :title="item.menuName" />
          </template>
          <sidebar-item
            v-for="child in item.children"
            :key="child.path"
            :is-nest="true"
            :item="child"
            class="nest-menu"
          />
        </el-submenu>
      </div>
    </template>
    
    <script>
    export default {
      props: {
        item: {
          type: Object,
          required: true
        },
        isNest: {
          type: Boolean,
          default: false
        },
        basePath: {
          type: String,
          default: ''
        }
      },
      data() {
        return {}
      },
      created() {},
      methods: {
      }
    }
    </script>
    
    5. router配置
    import Vue from 'vue'
    import Router from 'vue-router'
    
    Vue.use(Router)
    
    // 页面的布局存放
    /* Layout */
    import Layout from '@/layout'
    
    // 其他公共路由
    let constantRoutes = []
    constantRoutes = [
        {
            path: '/redirect',
            component: Layout,
            hidden: true,
            children: [
                {
                    path: '/redirect/:path(.*)',
                    component: () => import('@/views/redirect/index')
                }
            ]
        },
        {
            path: '/404',
            component: () => import('@/views/404'),
            hidden: true
        }
    ]
    
    // 拿到store数据
    let menuList = fnAddDynamicMenuRoutes(JSON.parse(localStorage.getItem('MENU_LIST')))
                    ? fnAddDynamicMenuRoutes(JSON.parse(localStorage.getItem('MENU_LIST')))
                    : []
    
    // 处理数据并引入对应的组件
    function fnAddDynamicMenuRoutes(routerList, routes = []) {
        // 用于保存普通路由数据
        let temp = []
        // 用于保存存在子路由的路由数据
        let route = []
        if (routerList && routerList.length) {
            // 遍历数据
            for (let i = 0; i < routerList.length; i++) {
                // 存在子路由,则递归遍历,并返回数据作为 children 保存
                if (routerList[i].children && routerList[i].children.length > 0) {
                    // 获取路由的基本格式
                    route = getRoute(routerList[i])
                    // 递归处理子路由数据,并返回,将其作为路由的 children 保存
                    route.children = fnAddDynamicMenuRoutes(routerList[i].children)
                    // 保存存在子路由的路由
                    routes.push(route)
                } else {
                    // 保存普通路由
                    temp.push(getRouteChild(routerList[i]))
                }
            }
            // 返回路由结果
            return routes.concat(temp)
        }
    }
    
    // 返回父级路由的基本格式
    function getRoute(item) {
        // 路由基本格式
        let route = Object.assign(item, {
            comp: item.component,
            // 路由的路径
            path: item.path,
            // 路由名
            name: item.menuName,
            // 路由的子路由
            children: item.children,
            icon: item.icon,
        });
        // 父级有子集处理 引入组件
        if (item.children) {
            route.component = Layout
            route.redirect = item.children[0].path
        } else { // 父级无子集处理 引入组件
            route.component = (resolve) => require([`@/views/${item.comp}`],resolve)
        }
        // 返回 route
        return route
    }
    
    // 返回子集路由的基本格式
    function getRouteChild(item) {
        // 路由基本格式
        // let name = `@/views/${item.component}`
        let route = Object.assign(item, {
            comp: item.component,
            // 路由的路径
            path: item.path,
            // 路由名
            name: item.menuName,
            // 路由所在组件  必须有一段已定义好的组件名字
            component: (resolve) => require([`@/views/${item.comp}`],resolve),
            // 路由的子路由
            children: item.children,
            icon: item.icon
        });
        // 返回 route
        return route
    }
    // 动态路由 与公共路由集合
    // constantRoutes = [...constantRoutes, ...menuList]
    constantRoutes = [...constantRoutes]
    export {
        constantRoutes
    }
    config = {
         mode: 'hash',
         scrollBehavior: () => ({y: 0}),
         routes: constantRoutes
    }
    const createRouter = () => new Router(config)
    const router = createRouter()
    
    export default router
    

    路由创建结束,仅供参考,看自己需求配置!!!!

    相关文章

      网友评论

          本文标题:vue2 el-menu 动态路由配置

          本文链接:https://www.haomeiwen.com/subject/srwigdtx.html