vue之递归组件
组件通过自身属性name进行递归调用自身组件渲染,
案例:实现页面tree菜单
父组件
<template>
<div class="home">
<!-- 首页左侧菜单区域 -->
<div class="aside">
<menu-aside :menuData="menuData"></menu-aside>
</div>
</div>
</template>
<script>
import MenuAside from './menu/menuAside'
export default {
name: 'home',
data() {
return {
menuData: [{//左侧菜单数据
name: '布局',
id: 'bj',
openFlag: false,
selectFlag: false,
level: 1,
children: [{
name: '三分布局',
id: 'sfbj',
openFlag: false,
selectFlag: false,
level: 2,
children: [{
name: '三级菜单',
id: 'sjcd',
openFlag: false,
selectFlag: false,
level: 3,
children: []
}]
}]
},{
name: '按钮',
id: 'an',
openFlag: false,
selectFlag: false,
level: 1,
path: '/button',
children: []
}],
}
},
components: {
MenuAside,//左侧菜单递归组件
}
}
</script>
子组件(递归组件)
<template>
<div class="menuAside">
<ul>
<li v-for="(item,index) in menuData" :key="item.id">
<div :class="['currentMenu',{childrenMenuSelect:item.selectFlag}]" @click="currentMenu(item,index)" >
<span class="leftIcon"></span>
<!-- item.level*20 通过层级进行层级缩进 -->
<span class="centerMenu" :style="{'padding-left': item.level*20 + 'px'}">{{item.name}}</span>
<span class="rightIcon" v-if="item.children&&item.children.length!=0">
<img src="../../assets/img/shangjiantou.png" alt="" v-if="!item.openFlag">
<img src="../../assets/img/jiantou.png" alt="" v-else>
</span>
</div>
<!-- item.children&&item.children.length!=0&&item.openFlag 通过菜单数据children进行结束递归渲染 -->
<div class="childrenMenu" v-if="item.children&&item.children.length!=0&&item.openFlag">
<menu-aside :menuData="item.children"></menu-aside>
</div>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'menuAside',
data() {
return {
}
},
props: {
// 菜单数据
menuData: {
type: Array,
default: [{
name: '标准菜单',
id: 'bzcd',
children: []
}]
}
},
created() {
},
methods: {
/**
* 点击当前菜单事件
*/
currentMenu: function(item,index) {
item.openFlag = !item.openFlag;//菜单层级展开收起
this.$store.commit('changeMenuEvent',item.id);//通过Vuex进行全局记录当前菜单切换并相应(选中样式渲染)进行操作
this.$router.push(item.path);//页面路由跳转
},
/**
* 循环重置菜单数据选中状态selectFlag
*/
cycleMenuData: function(lists) {
for(let item of lists) {
item.selectFlag = false;//清除当前菜单选中样式
if(this.$store.state.selectFlag == item.id) {//匹配当前选中菜单并渲染选中样式
item.selectFlag = true;
}
if(item.children&&item.children.length) {//结束循环条件
this.cycleMenuData(item.children);
}
}
},
},
watch: {
/**
* 通过VUex进行存储,监听左侧菜单切换-进行左侧菜单样式还原,当前活动菜单样式渲染及相关操作
*/
'$store.state.changeMenuFlag'(val) {
this.cycleMenuData(this.menuData);
}
},
}
</script>
通过Vuex进行菜单切换变量管理,解决菜单点击时样式渲染问题
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const store = new Vuex.Store({ state: { changeMenuFlag: false,//标记菜单切换进行菜单切换监听 selectFlag: null,//当前活动菜单id }, mutations: { /** * 菜单切换事件 */ changeMenuEvent: function(state,item) { state.changeMenuFlag = !state.changeMenuFlag;//菜单切换标记 state.selectFlag = item;//当前活动菜单id } } }) export default store
实现效果


浙公网安备 33010602011771号