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
实现效果