递归组件的使用
1.封装简单的Menu组件
代码目录结构如下:

router.js:
import Home from "@/views/Home.vue"; export default [ { path: "/", alias: "/home_page", name: "home", //加上name属性 命名路由 component: Home, props: route => ({ food: route.query.food }), beforeEnter: (to, from, next) => { // if (from.name === "about") alert("这是从about来的"); // else alert("这不是从about来的"); next(); } }, { path: '/menu_page', name: 'menu_page', component: () => import('@/views/menu-page.vue') }, { path: "*", component: () => import("@/views/error_404.vue") } ];
menu-page.vue:
<template>
<div class="menu-box">
<a-menu>
<a-menu-item>1111</a-menu-item>
<a-menu-item>2222</a-menu-item>
<a-submenu>
<div slot="title">3333</div>
<a-menu-item>3333-11</a-menu-item>
<a-submenu>
<div slot="title">3333-22</div>
<a-menu-item>3333-22-11</a-menu-item>
<a-menu-item>3333-22-22</a-menu-item>
</a-submenu>
</a-submenu>
</a-menu>
</div>
</template>
<script>
import menuComponents from "_c/menu";
const { AMenu, AMenuItem, ASubmenu } = menuComponents;
export default {
name: "menu_page",
components: {
AMenu,
AMenuItem,
ASubmenu
}
};
</script>
<style lang="less">
.menu-box {
width: 300px;
height: 400px;
}
</style>
a-menu.vue:
<template>
<div class="a-menu">
<slot></slot>
</div>
</template>
<script>
export default {
name: "AMenu"
};
</script>
<style lang="less">
.a-menu {
& * {
list-style: none;
}
ul {
padding: 0;
margin: 0;
}
}
</style>
a-menu-item.vue:
<template>
<li class="a-menu-item">
<slot></slot>
</li>
</template>
<script>
export default {
name: "AMenuItem"
};
</script>
<style lang="less">
.a-menu-item {
background: rgb(90, 92, 104);
color: #fff;
}
</style>
a-submenu.vue:
<template>
<ul class="a-submenu">
<div class="a-submenu-title" @click="handlerClick">
<slot name="title"></slot>
<span class="shrink-icon" :style="{transform:`rotateZ(${showChild ? 0 : 180}deg)`}">^</span>
</div>
<div v-show="showChild" class="a-submenu-child-box">
<slot></slot>
</div>
</ul>
</template>
<script>
export default {
name: "ASubmenu",
data() {
return {
showChild: false
};
},
methods: {
handlerClick() {
this.showChild = !this.showChild;
}
}
};
</script>
<style lang="less">
.a-submenu{
background: rgb(33, 35, 39);
&-title{
color: #fff;
position: relative;
.shrink-icon{
position:absolute;
top:0;
right: 10px;
}
}
&-child-box{
overflow: hidden;
padding-left: 20px;
}
li{
background: rgb(33, 35, 39);
}
}
</style>
运行效果:

2.递归组件
在以上提到的简单Menu的基础上,继续封装一个Recursivemenu(递归组件):

ReSubmenu.vue:
<template>
<a-submenu>
<div slot="title">{{ parent.title }}</div>
<template v-for="(item, i) in parent.children">
<a-menu-item v-if="!item.children" :key="`menu_item_${index}_${i}`">{{ item.title }}</a-menu-item>
<re-submenu v-else :key="`menu_item_${index}_${i}`" :parent="item"></re-submenu>
</template>
</a-submenu>
</template>
<script>
import menuComponents from '_c/menu'
const { AMenuItem, ASubmenu } = menuComponents
export default {
name: 'ReSubmenu',
components: {
AMenuItem,
ASubmenu
},
props: {
parent: {
type: Object,
default: () => ({})
},
index: Number
}
}
</script>
index.js:
import ReSubmenu from "./ReSubmenu.vue"; export default ReSubmenu;
menu-page.vue:
<template>
<div class="menu-box">
<a-menu>
<template v-for="(item, index) in list">
<a-menu-item v-if="!item.children" :key="`menu_item_${index}`">{{ item.title }}</a-menu-item>
<re-submenu v-else :key="`menu_item_${index}`" :parent="item" :index="index"></re-submenu>
</template>
</a-menu>
</div>
</template>
<script>
import menuComponents from "_c/menu";
import ReSubmenu from "_c/Recursivemenu";
const { AMenu, AMenuItem, ASubmenu } = menuComponents;
export default {
name: "menu_page",
components: {
AMenu,
AMenuItem,
ASubmenu,
ReSubmenu
},
data() {
return {
list: [
{
title: "1111"
},
{
title: "2222"
},
{
title: "3333",
children: [
{
title: "3333-1"
},
{
title: "3333-2",
children: [
{
title: "3333-2-1"
},
{
title: "3333-2-2"
},
{
title: "3333-2-3",
children: [
{
title: "3333-2-3-1"
},
{
title: "3333-2-3-2"
}
]
}
]
}
]
},
{
title: "4444"
}
]
};
}
};
</script>
<style lang="less">
.menu-box {
width: 300px;
height: 400px;
}
</style>
运行效果:

浙公网安备 33010602011771号