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

实现效果

原文地址:https://www.cnblogs.com/emilyzz/p/14251133.html