首先我们需要明确一下什么是递归组件。顾名思义,递归组件就是在组件内部使用该组件本身。在树形结构的数据展示中,经常会使用到递归组件来展示子节点。
接下来我将以“用 Vue.js 递归组件实现可折叠的树形菜单(demo)”为例,讲解一下如何使用递归组件来实现树形菜单的效果。
- 定义组件
首先我们需要定义一个组件,用于展示每一个菜单项。该组件需要有以下特点:
- 显示菜单文字
- 点击可展开/折叠子菜单
- 当前菜单被选中时需要高亮
我们将该组件命名为Menu:
<template>
<li>
<div @click="toggleShowChildren">
<span :class="{ 'active': isActive }">{{menuItem.name}}</span>
<span v-if="menuItem.children" :class="{ 'arrow': true, 'down': showChildren, 'right': !showChildren }"></span>
</div>
<ul v-show="showChildren">
<menu-item v-for="(item, index) in menuItem.children" :key="index" :menu-item="item" :deep="deep+1"></menu-item>
</ul>
</li>
</template>
<script>
export default {
name: 'MenuItem',
props: {
menuItem: Object,
deep: {
type: Number,
default: 1
}
},
data() {
return {
showChildren: false
}
},
computed: {
isActive() {
return this.menuItem.active
}
},
methods: {
toggleShowChildren() {
if (this.menuItem.children) {
this.showChildren = !this.showChildren
}
}
},
components: {
MenuItem
}
}
</script>
<style>
.active {
color: red;
}
li .arrow {
display: inline-block;
width: 0;
height: 0;
margin-left: 5px;
border-top: 4px solid transparent;
border-right: 5px solid;
border-bottom: 4px solid transparent;
vertical-align: middle;
cursor: pointer;
}
li .arrow.down {
border-top: 4px solid;
border-right: 5px solid transparent;
border-bottom: 4px solid transparent;
}
ul {
margin-left: 10px;
padding: 0;
list-style: none;
border-left: 1px solid #ccc;
}
li {
padding: 5px 0;
position: relative;
}
</style>
在该组件中,我们使用了递归的方式展示菜单的子节点。循环遍历传入的menuItem.children
数组,如果该菜单项有子菜单,则将该子菜单传入Menu组件中进行展示。
- 使用递归组件
接下来,我们需要引入顶层的菜单组件,并传入菜单数据。
<template>
<div class="app">
<ul>
<menu-item v-for="(item, index) in menuData" :key="index" :menu-item="item"></menu-item>
</ul>
</div>
</template>
<script>
import MenuItem from './components/MenuItem.vue'
export default {
components: {
MenuItem
},
data() {
return {
menuData: [
{
name: '菜单1',
active: false,
children: [
{
name: '菜单1-1',
active: false,
children: [
{
name: '菜单1-1-1',
active: false,
},
{
name: '菜单1-1-2',
active: false,
}
]
},
{
name: '菜单1-2',
active: false,
}
]
},
{
name: '菜单2',
active: false,
children: [
{
name: '菜单2-1',
active: false
},
{
name: '菜单2-2',
active: false
}
]
}
]
}
}
}
</script>
<style scoped>
ul {
margin: 0;
padding: 0;
list-style: none;
}
</style>
在该组件中,我们引入了MenuItem,并将根菜单数据menuData
传入到MenuItem中进行渲染。
- 显示菜单高亮
要实现显示菜单高亮效果,我们需要使用Vue.js中的路由功能。首先我们需要引入Vue Router,并在router/index.js中定义好路由规则。
然后,在Menu组件中,我们需要判断当前菜单项是否与路由信息相符。如果相符,则将该菜单项设置为选中状态。代码如下所示:
<script>
import { mapState } from 'vuex'
export default {
name: 'MenuItem',
props: {
menuItem: Object,
deep: {
type: Number,
default: 1
}
},
data() {
return {
showChildren: false
}
},
computed: {
...mapState({
currentPath: state => state.route.path
}),
isActive() {
return this.menuItem.active
}
},
methods: {
toggleShowChildren() {
if (this.menuItem.children) {
this.showChildren = !this.showChildren
}
}
},
components: {
MenuItem
},
watch: {
currentPath() {
if (this.menuItem.path === this.currentPath) {
this.menuItem.active = true
} else {
this.menuItem.active = false
}
}
}
}
</script>
在上述代码中,我们引入了Vuex中的mapState方法,获取当前路由信息currentPath
。然后,在watch中监听路由信息变化,判断当前菜单项的路由信息是否与当前路由信息相同。如果相同,将该菜单项设置为选中状态。
综上所述,以上是用Vue.js递归组件实现可折叠的树形菜单(demo)的完整攻略。其中包括了组件的定义、递归调用、显示高亮等功能。您可以参考代码进行实践,也可以在此基础上进行二次开发。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:用 Vue.js 递归组件实现可折叠的树形菜单(demo) - Python技术站