前言
之前簡單的封裝了一下菜單組件,數(shù)據(jù)都是寫死的,多層嵌套沒有支持,學(xué)完了組件傳值,計(jì)算屬性就可以繼續(xù)完善了。
多層菜單封裝
先看下數(shù)據(jù)結(jié)構(gòu):
{
"id":"1",
"name":"系統(tǒng)管理",
"path":"/system",
"hidden":false,
"icon":"mdi:mdi-minus",
"component":"",
"redirect":"noDirect",
"children": [
{
"id":"11",
"name":"用戶管理",
"path":"/user",
"hidden":false,
"icon":"mdi:mdi-account",
"component":"",
"redirect":"noDirect",
"children":[
{
"id":"111",
"name":"小白兔",
"path":"/user",
"hidden":false,
"icon":"mdi-account",
"component":"",
"redirect":"noDirect",
"children":[]
}
]
}
]
}
數(shù)據(jù)有多層,所以使用嵌套,定義一個(gè)item組件NavigationItem.vue:
<template>
<div v-if=hasChildren>
<v-list-group :value="navigationItem.name">
<template v-slot:activator="{ props }">
<v-list-item
v-bind="props"
:title="navigationItem.name"
prepend-icon="mdi:mdi-minus"
></v-list-item>
</template>
<NavigationItem v-for="child in navigationItem.children"
:key = child.id
:navigationItem = child
>
</NavigationItem>
</v-list-group>
</div>
<div v-else >
<v-list-item :prepend-icon="navigationItem.icon" :title="navigationItem.name" :value="navigationItem.name"></v-list-item>
</div>
</template>
<script lang='ts' setup name="Navigation">
import { computed, onMounted, ref } from 'vue';
import {NavigationItemInterface} from '@/types'
const {navigationItem} = defineProps<{navigationItem:NavigationItemInterface}>()
//組合式計(jì)算屬性寫法
let hasChildren = computed(()=>{
return navigationItem.children.length>0
})
</script>
重點(diǎn)思路:如果有子節(jié)點(diǎn)就展示v-list-group,然后調(diào)用自己,如果沒有子節(jié)點(diǎn)就展示v-list-item。
父組件還用之前的Navigation.vue,修改成調(diào)用子組件并傳值:
<template>
<v-navigation-drawer
v-model="drawer"
:rail="rail"
permanent
@click="rail = false"
>
<v-list-item
prepend-avatar="https://randomuser.me/api/portraits/men/88.jpg"
title="John Leider"
nav
>
<template v-slot:append>
<v-btn
variant="text"
icon="mdi:mdi-chevron-left"
@click.stop="rail = !rail"
></v-btn>
</template>
</v-list-item>
<v-divider></v-divider>
<!-- 菜單---start -->
<v-list density="compact" nav>
<NavigationItem
v-for="navigationItem in navigationItems"
:navigationItem = "navigationItem"
:key = navigationItem.id
></NavigationItem>
</v-list>
<!-- 菜單---end -->
</v-navigation-drawer>
</template>
<script lang='ts' setup name="Navigation">
import { ref } from 'vue';
let drawer=ref(true)
let rail=ref(false)//false代表展開
let navigationItems = ref([
{
"id":"1",
"name":"系統(tǒng)管理",
"path":"/system",
"hidden":false,
"icon":"mdi:mdi-minus",
"component":"",
"redirect":"noDirect",
"children": [
{
"id":"11",
"name":"用戶管理",
"path":"/user",
"hidden":false,
"icon":"mdi:mdi-account",
"component":"",
"redirect":"noDirect",
"children":[
{
"id":"111",
"name":"小白兔",
"path":"/user",
"hidden":false,
"icon":"mdi-account",
"component":"",
"redirect":"noDirect",
"children":[]
}
]
}
]
},
{
"id":"2",
"name":"開發(fā)工具",
"path":"/system",
"hidden":false,
"icon":"mdi:mdi-tools",
"component":"",
"redirect":"noDirect",
"children":[]
},
{
"id":"3",
"name":"UI元素",
"path":"/contact",
"hidden":false,
"icon":"mdi:mdi-ubisoft",
"component":"",
"redirect":"noDirect",
"children":[]
},
{
"id":"4",
"name":"聯(lián)系我們",
"path":"/contact",
"hidden":false,
"icon":"mdi:mdi-contacts",
"component":"",
"redirect":"noDirect",
"children":[]
},
])
</script>
子組件接口定義:
export interface NavigationItemInterface{
children: Array<NavigationItemInterface>,
id:string,
name:string,
hidden:boolean,
icon:string,
component:string,
redirect:string,
path:string
}
效果展示:

image.png
總結(jié)
在前文的基礎(chǔ)上對(duì)左側(cè)導(dǎo)航欄組件完善了一下。
心向陽光,陰影自退。