vue3+Element采用递归调用封装导航栏

打印 上一主题 下一主题

主题 803|帖子 803|积分 2409

vue3+Element采用递归调用封装导航栏

效果预览


模拟数据


  • 数据来源有很多,可以是自己写死的,也可以是后端调用得到的,也可以从别的组件中拿到
  • 这里采用从路由中拿
  • 定义数据源src/router/module.js/
  1. const Login = () => import('../views/Login/Login.vue');
  2. const Layout = () => import('../layout/layout.vue');
  3. const Home = () => import('../views/Home.vue');
  4. const User = () => import('../views/About.vue');
  5. const Avatar = () => import('../views/Users/Avatar.vue');
  6. const Password = () => import('../views/Users/Password.vue');
  7. const routes = [
  8.   {
  9.     path: '/',
  10.     redirect: '/home',
  11.   },
  12.   {
  13.     path: '/',
  14.     name: 'Layout',
  15.     component: Layout,
  16.     meta: {
  17.       permission: true,
  18.     },
  19.     children: [
  20.       {
  21.         path: '/home',
  22.         name: 'Home',
  23.         component: Home,
  24.         meta: {
  25.           title: '首页',
  26.           icon: '', // iconfont图标
  27.           inSide: true,
  28.         },
  29.       },
  30.       {
  31.         path: '/user',
  32.         name: 'User',
  33.         component: User,
  34.         meta: {
  35.           title: '个人中心',
  36.           icon: '',
  37.         },
  38.         children: [
  39.           {
  40.             path: '/user/avatar',
  41.             name: 'Avatar',
  42.             component: Avatar,
  43.             meta: {
  44.               title: '修改头像',
  45.             },
  46.             children: [
  47.               {
  48.                 path: '/setUp/avatar',
  49.                 name: 'setUp',
  50.                 component: Avatar,
  51.                 meta: {
  52.                   title: '暂无',
  53.                 },
  54.               },
  55.             ],
  56.           },
  57.           {
  58.             path: '/user/password',
  59.             name: 'Password',
  60.             component: Password,
  61.             meta: {
  62.               title: '修改密码',
  63.             },
  64.           },
  65.         ],
  66.       },
  67.       {
  68.         path: '/setUp',
  69.         name: 'SetUp',
  70.         meta: {
  71.           title: '系统设置',
  72.           icon: '',
  73.         },
  74.         children: [
  75.           {
  76.             path: '/setUp/avatar',
  77.             name: 'setUp',
  78.             component: Avatar,
  79.             meta: {
  80.               title: '暂无',
  81.             },
  82.           },
  83.           {
  84.             path: '/setUp/avatar',
  85.             name: 'setUp',
  86.             component: Avatar,
  87.             meta: {
  88.               title: '暂无',
  89.             },
  90.           },
  91.         ],
  92.       },
  93.     ],
  94.   },
  95.   {
  96.     path: '/login',
  97.     name: 'Login',
  98.     component: Login,
  99.   },
  100. ];
  101. export default routes;
复制代码
递归实现导航栏渲染



  • 对于导航栏渲染难点在于不知道有多少层级的导航,可能一级也可能两级或者更多
  • 为了方便采用两个组件父组件aside.vue与子组件subAside.vue渲染导航
  • 这时候就需要采用递归的方式

    • 首先判断哪些数据需要渲染,需要的拿出来
    • 判断是否有子节点需要渲染

      • 有子节点,递归调用子组件本身
      • 没有子节点,返回导航项进行渲染


父组件aside.vue

  1. <template>
  2.   <el-radio-group v-model="isCollapse" style="margin-bottom: 20px">
  3.     <el-radio-button :label="false">expand</el-radio-button>
  4.     <el-radio-button :label="true">collapse</el-radio-button>
  5.   </el-radio-group>
  6.   <el-menu
  7.       default-active="2"
  8.       class="el-menu-vertical-demo"
  9.       :collapse="isCollapse"
  10.       select="handleSelect"
  11.       router
  12.       unique-opened
  13.   >
  14.    
  15.     <SubAside :isCollapse="isCollapse" v-for="(item,index) in navs" :key="item.path" :menu="item" :index="item.path" />
  16.   </el-menu>
  17. </template>
复制代码
父组件处理后的用于渲染的数据
  1. [
  2.         {
  3.                 component: () => import('/src/views/Home.vue')
  4.                 meta: {title: '首页', icon: '', inSide: true}
  5.                 name: "Home"
  6.                 path: "/home"
  7.         },
  8.         {
  9.                 component: () => import('/src/views/About.vue')
  10.                 meta: {title: '个人中心', icon: ''}
  11.                 name: "User"
  12.                 path: "/user"
  13.                 chilren:[
  14.                 {
  15.                         children: [{…}]
  16.                         component: () => import('/src/views/Users/Avatar.vue?t=1655544364909')
  17.                         meta: {title: '修改头像'}
  18.                         name: "Avatar"
  19.                         path: "/user/avatar"
  20.                 },
  21.                 {
  22.                         component: () => import('/src/views/Users/Password.vue')
  23.                         meta: {title: '修改密码'}
  24.                         name: "Password"
  25.                         path: "/user/password"
  26.                 }
  27.                 ]
  28.         },
  29.         {
  30.                 meta: {title: '系统设置', icon: ''}
  31.                 name: "SetUp"
  32.                 path: "/setUp"
  33.                 chilren:[
  34.                 {
  35.                         component: () => import('/src/views/Users/Avatar.vue?t=1655544364909')
  36.                         meta: {title: '暂无'}
  37.                         name: "setUp"
  38.                         path: "/setUp/avatar"
  39.                 },
  40.                 {
  41.                         component: () => import('/src/views/Users/Avatar.vue?t=1655544364909')
  42.                         meta: {title: '暂无'}
  43.                         name: "setUp"
  44.                         path: "/setUp/avatar"
  45.                 }
  46.                 ]
  47.         }
  48. ]
复制代码
子组件subAside.vue

  1. <template>
  2.    
  3.     <el-sub-menu :index="menu.path" v-if="menu?.children">
  4.         <template #title>
  5.             <el-icon v-html="menu?.meta.icon"></el-icon>
  6.             {{menu?.meta.title}}
  7.         </template>
  8.         
  9.         <SubAside v-for="item in menu.children" :menu="item" :isCollapse="isCollapse"/>
  10.     </el-sub-menu>
  11.    
  12.     <el-menu-item  v-else  :index="menu?.path">
  13.             <el-icon v-html="menu?.meta.icon"></el-icon>
  14.             {{menu?.meta.title}}
  15.     </el-menu-item >
  16.   
  17. </template>
  18.    
复制代码
配置


  • 版本
  1. "vue": "^3.2.25",
  2. "element-plus": "^2.2.6",
复制代码

  • main.ts中配置
  1. import { createApp } from 'vue';
  2. import App from './App.vue';
  3. // import 'virtual:windi.css';
  4. import router from './router/index';
  5. /**
  6. * 引入elment
  7. */
  8. import ElementPlus from 'element-plus'
  9. import 'element-plus/dist/index.css'
  10. import 'element-plus/theme-chalk/dark/css-vars.css'
  11. import './styles/dark/css-vars.css'
  12. // 引入 Pinia 状态管理工具
  13. import pinia from './stores'
  14. const app=createApp(App)
  15. /**
  16.   * 全局注册组件
  17.   */
  18. import SubAside from './components/subAside.vue'
  19. app.component('SubAside', SubAside)
  20. // 注册Element全局可用
  21. app.use(ElementPlus).use(router).use(pinia).mount('#app');
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用多少眼泪才能让你相信

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表