vue3+Element采用遞歸調(diào)用封裝導(dǎo)航欄實現(xiàn)
效果預(yù)覽

模擬數(shù)據(jù)
- 數(shù)據(jù)來源有很多,可以是自己寫死的,也可以是后端調(diào)用得到的,也可以從別的組件中拿到
- 這里采用從路由中拿
- 定義數(shù)據(jù)源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: '<span class="iconfont icon-shouye"/>', // iconfont圖標
inSide: true,
},
},
{
path: '/user',
name: 'User',
component: User,
meta: {
title: '個人中心',
icon: '<span class="iconfont icon-yonghuzhongxin1"/>',
},
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: '系統(tǒng)設(shè)置',
icon: '<span class="iconfont icon-celveguanli"/>',
},
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;
遞歸實現(xiàn)導(dǎo)航欄渲染
- 對于導(dǎo)航欄渲染難點在于不知道有多少層級的導(dǎo)航,可能一級也可能兩級或者更多
- 為了方便采用兩個組件父組件aside.vue與子組件subAside.vue渲染導(dǎo)航
- 這時候就需要采用遞歸的方式
- 首先判斷哪些數(shù)據(jù)需要渲染,需要的拿出來
- 判斷是否有子節(jié)點需要渲染
- 有子節(jié)點,遞歸調(diào)用子組件本身
- 沒有子節(jié)點,返回導(dǎo)航項進行渲染
父組件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
>
<!-- 將渲染導(dǎo)航每一項傳給子組件渲染,item代表要渲染每一項 -->
<SubAside :isCollapse="isCollapse" v-for="(item,index) in navs" :key="item.path" :menu="item" :index="item.path" />
</el-menu>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import router from '../router/module';
const navs =router.filter((item) => item.meta?.permission)[0].children // 過濾拿到數(shù)據(jù)
console.log(navs);
const isCollapse = ref(true); // 是否收起,默認不收起
</script>
<style lang="scss" scoped></style>
父組件處理后的用于渲染的數(shù)據(jù)
[
{
component: () => import('/src/views/Home.vue')
meta: {title: '首頁', icon: '<span class="iconfont icon-shouye"/>', inSide: true}
name: "Home"
path: "/home"
},
{
component: () => import('/src/views/About.vue')
meta: {title: '個人中心', icon: '<span class="iconfont icon-yonghuzhongxin1"/>'}
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: '系統(tǒng)設(shè)置', icon: '<span class="iconfont icon-celveguanli"/>'}
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>
<!-- 有子節(jié)點渲染這個 -->
<el-sub-menu :index="menu.path" v-if="menu?.children">
<template #title>
<el-icon v-html="menu?.meta.icon"></el-icon>
<span>{{menu?.meta.title}}</span>
</template>
<!-- 遞歸調(diào)用本身,該組件在index.ts中全局注冊了 -->
<SubAside v-for="item in menu.children" :menu="item" :isCollapse="isCollapse"/>
</el-sub-menu>
<!-- 沒有子節(jié)點渲染這個 -->
<el-menu-item v-else :index="menu?.path">
<el-icon v-html="menu?.meta.icon"></el-icon>
<span slot="title">{{menu?.meta.title}}</span>
</el-menu-item >
</template>
<script lang="ts" setup>
import { ref } from "vue"
// 拿到父組件傳入的值
defineProps({
isCollapse:Boolean,
menu:Object
})
</script>
<style lang="scss" scoped>
</style>
配置
版本
"vue": "^3.2.25", "element-plus": "^2.2.6",
main.ts中配置
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 狀態(tài)管理工具
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');
到此這篇關(guān)于vue3+Element采用遞歸調(diào)用封裝導(dǎo)航欄實現(xiàn)的文章就介紹到這了,更多相關(guān)vue3 Element封裝導(dǎo)航欄內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue使用axios實現(xiàn)文件上傳進度的實時更新詳解
最近在學習axios,然后項目就用到了,所以這篇文章主要給大家介紹了關(guān)于vue中利用axios實現(xiàn)文件上傳進度的實時更新的相關(guān)資料,文中先對axios進行了簡單的介紹,方法大家理解學習,需要的朋友們下面隨著小編來一起學習學習吧。2017-12-12
vue3自定義組件之v-model實現(xiàn)父子組件雙向綁定
這篇文章主要介紹了vue3自定義組件之v-model實現(xiàn)父子組件雙向綁定方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08
vue-music 使用better-scroll遇到輪播圖不能自動輪播問題
根據(jù)vue-music視頻中slider組建的使用,當安裝新版本的better-scroll,輪播組件,不能正常輪播。如何解決這個問題呢,下面小編給大家?guī)砹藇ue-music 使用better-scroll遇到輪播圖不能自動輪播問題,感興趣的朋友一起看看吧2018-12-12
Vue 2源碼解析HTMLParserOptions.start函數(shù)方法
這篇文章主要為大家介紹了Vue 2源碼解析HTMLParserOptions.start函數(shù)方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08

