vue3+Element采用递归调用封装导航栏
效果预览
模拟数据
- 数据来源有很多,可以是自己写死的,也可以是后端调用得到的,也可以从别的组件中拿到
- 这里采用从路由中拿
- 定义数据源src/router/module.js/
- const Login = () => import('../views/Login/Login.vue');
- const Layout = () => import('../layout/layout.vue');
- const Home = () => import('../views/Home.vue');
- const User = () => import('../views/About.vue');
- const Avatar = () => import('../views/Users/Avatar.vue');
- const Password = () => import('../views/Users/Password.vue');
- const routes = [
- {
- path: '/',
- redirect: '/home',
- },
- {
- path: '/',
- name: 'Layout',
- component: Layout,
- meta: {
- permission: true,
- },
- children: [
- {
- path: '/home',
- name: 'Home',
- component: Home,
- meta: {
- title: '首页',
- icon: '', // iconfont图标
- inSide: true,
- },
- },
- {
- path: '/user',
- name: 'User',
- component: User,
- meta: {
- title: '个人中心',
- icon: '',
- },
- children: [
- {
- path: '/user/avatar',
- name: 'Avatar',
- component: Avatar,
- meta: {
- title: '修改头像',
- },
- children: [
- {
- path: '/setUp/avatar',
- name: 'setUp',
- component: Avatar,
- meta: {
- title: '暂无',
- },
- },
- ],
- },
- {
- path: '/user/password',
- name: 'Password',
- component: Password,
- meta: {
- title: '修改密码',
- },
- },
- ],
- },
- {
- path: '/setUp',
- name: 'SetUp',
- meta: {
- title: '系统设置',
- icon: '',
- },
- children: [
- {
- path: '/setUp/avatar',
- name: 'setUp',
- component: Avatar,
- meta: {
- title: '暂无',
- },
- },
- {
- path: '/setUp/avatar',
- name: 'setUp',
- component: Avatar,
- meta: {
- title: '暂无',
- },
- },
- ],
- },
- ],
- },
- {
- path: '/login',
- name: 'Login',
- component: Login,
- },
- ];
- export default routes;
复制代码 递归实现导航栏渲染
- 对于导航栏渲染难点在于不知道有多少层级的导航,可能一级也可能两级或者更多
- 为了方便采用两个组件父组件aside.vue与子组件subAside.vue渲染导航
- 这时候就需要采用递归的方式
- 首先判断哪些数据需要渲染,需要的拿出来
- 判断是否有子节点需要渲染
- 有子节点,递归调用子组件本身
- 没有子节点,返回导航项进行渲染
父组件aside.vue
- <template>
- <el-radio-group v-model="isCollapse" style="margin-bottom: 20px">
- <el-radio-button :label="false">expand</el-radio-button>
- <el-radio-button :label="true">collapse</el-radio-button>
- </el-radio-group>
- <el-menu
- default-active="2"
- class="el-menu-vertical-demo"
- :collapse="isCollapse"
- select="handleSelect"
- router
- unique-opened
- >
-
- <SubAside :isCollapse="isCollapse" v-for="(item,index) in navs" :key="item.path" :menu="item" :index="item.path" />
- </el-menu>
- </template>
复制代码 父组件处理后的用于渲染的数据
- [
- {
- component: () => import('/src/views/Home.vue')
- meta: {title: '首页', icon: '', inSide: true}
- name: "Home"
- path: "/home"
- },
- {
- component: () => import('/src/views/About.vue')
- meta: {title: '个人中心', icon: ''}
- name: "User"
- path: "/user"
- chilren:[
- {
- children: [{…}]
- component: () => import('/src/views/Users/Avatar.vue?t=1655544364909')
- meta: {title: '修改头像'}
- name: "Avatar"
- path: "/user/avatar"
- },
- {
- component: () => import('/src/views/Users/Password.vue')
- meta: {title: '修改密码'}
- name: "Password"
- path: "/user/password"
- }
- ]
- },
- {
- meta: {title: '系统设置', icon: ''}
- name: "SetUp"
- path: "/setUp"
- chilren:[
- {
- component: () => import('/src/views/Users/Avatar.vue?t=1655544364909')
- meta: {title: '暂无'}
- name: "setUp"
- path: "/setUp/avatar"
- },
- {
- component: () => import('/src/views/Users/Avatar.vue?t=1655544364909')
- meta: {title: '暂无'}
- name: "setUp"
- path: "/setUp/avatar"
- }
- ]
- }
- ]
复制代码 子组件subAside.vue
- <template>
-
- <el-sub-menu :index="menu.path" v-if="menu?.children">
- <template #title>
- <el-icon v-html="menu?.meta.icon"></el-icon>
- {{menu?.meta.title}}
- </template>
-
- <SubAside v-for="item in menu.children" :menu="item" :isCollapse="isCollapse"/>
- </el-sub-menu>
-
- <el-menu-item v-else :index="menu?.path">
- <el-icon v-html="menu?.meta.icon"></el-icon>
- {{menu?.meta.title}}
- </el-menu-item >
-
- </template>
-
复制代码 配置
- "vue": "^3.2.25",
- "element-plus": "^2.2.6",
复制代码- import { createApp } from 'vue';
- import App from './App.vue';
- // import 'virtual:windi.css';
- import router from './router/index';
- /**
- * 引入elment
- */
- import ElementPlus from 'element-plus'
- import 'element-plus/dist/index.css'
- import 'element-plus/theme-chalk/dark/css-vars.css'
- import './styles/dark/css-vars.css'
- // 引入 Pinia 状态管理工具
- import pinia from './stores'
- const app=createApp(App)
- /**
- * 全局注册组件
- */
- import SubAside from './components/subAside.vue'
- app.component('SubAside', SubAside)
- // 注册Element全局可用
- app.use(ElementPlus).use(router).use(pinia).mount('#app');
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |