六.导航(菜单)
前言 --> 菜单组件特点
递归组件就是组件在模板中调用自己,需要满足两个条件:
- 在组件中设置一个
name
选项,通过这个字段拿到组件 - 加上结束条件,防止一直递归下去,抛出
max stack size exeeded
错误
1.目录结构
sh
├── table
│ ├── dropdown-item.vue
│ ├── dropdown-menu.vue
│ ├── dropdown.vue
│ └── index.js
1.实现方式
vue
<template>
<my-component :count="count + 1" v-if="count <= 5"></my-component> <!-- 2.添加限定条件 -->
</template>
<script>
export default {
name: "my-component", // 1.添加名称标识
props: {
count: {
type: Number,
default: 1,
},
},
}
</script>
提示
递归组件常用来开发具有位置层级关系的独立组件,这类组件一般都是数据驱动型的,父级有一个字段 children,然后递归
2.使用案例
使用 vue 的递归组件写一个菜单组件,实现无限菜单
App.vue 案例
vue
<template>
<div id="app">
<Menu>
<template v-for="menu in menuList">
<MenuItem :key="menu.title" v-if="!menu.children">
{{ menu.title }}
</MenuItem>
<ReSubMenu :key="menu.title" v-else :data="menu"></ReSubMenu>
</template>
</Menu>
</div>
</template>
<script>
import Menu from "./Menu"
import MenuItem from "./MenuItem"
import SubMenu from "./SubMenu"
import ReSubMenu from "./ReSubMenu"
export default {
data() {
return {
msg: "hello",
menuList: [
{
title: "菜单1",
children: [
{
title: "菜单1-1",
children: [
{ title: "菜单1-1-1" },
{ title: "菜单1-1-2" },
{
title: "菜单1-1-3",
children: [
{ title: "菜单1-1-1" },
{ title: "菜单1-1-2" },
{
title: "菜单1-1-3",
children: [
{ title: "菜单1-1-1" },
{ title: "菜单1-1-2" },
{
title: "菜单1-1-3",
children: [
{ title: "菜单1-1-1" },
{ title: "菜单1-1-2" },
{ title: "菜单1-1-3" },
],
},
],
},
],
},
],
},
{ title: "菜单1-2" },
{ title: "菜单1-3" },
],
},
{
title: "菜单2",
},
{
title: "菜单3",
},
],
}
},
components: {
Menu,
MenuItem,
SubMenu,
ReSubMenu,
},
}
</script>
<style>
#app {
color: red;
}
</style>
- Menu.vue
vue
<template>
<ul class="menu">
<slot></slot>
</ul>
</template>
- MenuItem
vue
<template>
<li>
<slot></slot>
</li>
</template>
- ReSubMenu.vue
vue
<template>
<SubMenu>
<template #title>
{{ data.title }}
</template>
<template v-for="child in data.children">
<!-- 如果没儿子 直接渲染MenuItem 如果有儿子 将儿子递归传入 -->
<MenuItem :key="child.title" v-if="!child.children">{{
child.title
}}</MenuItem>
<ReSub v-else :key="child.title" :data="child"></ReSub>
</template>
</SubMenu>
</template>
<script>
import SubMenu from "./SubMenu"
import MenuItem from "./MenuItem"
export default {
name: "ReSub", //可以使用递归组件
props: {
data: {
type: Object,
default: () => ({}),
},
},
components: {
SubMenu,
MenuItem,
},
}
</script>
- SubMenu.vue
vue
<template>
<div>
<div class="title" @click="change">
<slot name="title"></slot>
</div>
<div v-show="flag" class="sub">
<slot></slot>
</div>
</div>
</template>
<script>
export default {
data() {
return { flag: false }
},
methods: {
change() {
this.flag = !this.flag
},
},
}
</script>
<style>
.sub {
padding-left: 10px;
}
</style>
3.使用场景
<template>
<vue-button>按钮</vue-button>
</template>
总结
合理使用动态组件可以让我们写出的代码更加简洁,减少冗余代码