文章目录
- 前言
- 多层菜单封装
- 总结
前言
之前简单的封装了一下菜单组件,数据都是写死的,多层嵌套没有支持,学完了组件传值,计算属性就可以继续完善了。
多层菜单封装
先看下数据结构:
{
"id":"1",
"name":"系统管理",
"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":[]
}
]
}
]
}
数据有多层,所以使用嵌套,定义一个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}>()
//组合式计算属性写法
let hasChildren = computed(()=>{
return navigationItem.children.length>0
})
</script>
重点思路:如果有子节点就展示v-list-group,然后调用自己,如果没有子节点就展示v-list-item。
父组件还用之前的Navigation.vue,修改成调用子组件并传值:
<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":"系统管理",
"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":"开发工具",
"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":"联系我们",
"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
}
效果展示:
总结
在前文的基础上对左侧导航栏组件完善了一下。
心向阳光,阴影自退。