vue组件递归(vue 通过 组件递归 实现多级菜单渲染)

如果菜单嵌套层数是已知的可以通过 v-for 循环出要渲染的菜单,但是如果我们不知道我们要循环多少层子菜单,那么这个时候 v-for 就不能解决问题了

要实现动态的渲染我们拿到的不知道有几层的菜单数据,有两种解决方案:

  • 操作 dom 去一层一层 添加子菜单(vue 不推荐操作 dom,所以不推荐此方案)
  • 将我们的菜单封装到组件中,通过递归组件实现菜单渲染

先贴一个 demo
demo地址:https://download.csdn.net/download/qq_25992675/12853870

  1. 动态的渲染菜单
  2. 可以通过点击菜单渲染加载子菜单

在这里插入图片描述

其实组件递归很简单,在组件中调用自己不需要引入注册自己,只需要通过组件的 name 在页面中通过标签的形式调用自己即可


组件递归的使用

这里只是贴的代码片段主要是介绍组件递归的使用,想看完整demo的可以下载demo

组件声明

注意点:

  1. Menu:组件的 name,可以通过定义的 name: “Menu” 作为标签来调用自己
  2. 要给组件加上 @click.stop 属性,防止在点击子菜单或空白部分触发父菜单点击事件
  3. 因为我的菜单有自己的选中样式所以在class上有一些三元判断,具体可以根据自己需求定义
<template>
<div class="menu" @click.stop>
    <div v-for="(item, index) in menuList" :key="index" @click.stop :class="menu-item" @click="chooseMenu(index, item)">
        <span :class="item.checkIndex == index ? 'name choose-item' : 'name'">{
    
    {
    
    
        item.name
      }}</span>
        <span :class="item.checkIndex == index ? 'index choose-item' : 'index'">
            {
    
    {
    
     index + 1 }}
        </span>
        <Menu class="menu-children" :menuList="item.childrens" @back="back(index, $event)"></Menu>
    </div>
</div>
</template>

<script>
export default {
    
    
    name: "Menu",
    props: {
    
    
        menuList: Array,
    },
    methods: {
    
    
        /**
         * @author: yx
         * @method: 选择菜单,返回菜单信息以及列下标
         * @Date: 2020-09-17 10:40:18
         */
        chooseMenu(index, item) {
    
    
            let child = {
    
    
                index: [index],
                item,
            };
            this.$emit("back", child);
        },
        /**
         * @author: yx
         * @method: 向上次依次返回选择的菜单信息以及列下标
         * @Date: 2020-09-17 10:40:27
         */
        back(index, event) {
    
    
            event.index.push(index);
            this.$emit("back", event);
        },
    },
};
</script>

组件调用

注意点:

  1. 因为每次选择样式都需要变化,但是更改了 menList 的值之后递归组件并不能第一时间更新dom,所以在这里我定义了一个 refresh,通过 refresh 来刷新组件
<template>
	<div class="home">
	    <Menu v-if="refresh" :menuList="menuList" @back="back($event)"></Menu>
	</div>
</template>

<script>
import Menu from "../components/menu";
export default {
    
    
  name: "Home",
   data() {
    
    
        return {
    
    
            refresh: true,
            menuList: [{
    
    
                id: 1,
                name: "测试",
                checkIndex: 0,
                isFirst: true,
                childrens: [{
    
    
                   id: 2,
                    name: "测试1级1",
                    checkIndex: 0,
                    childrens: [{
    
    
                        id: 6,
                         name: "测试2级1",
                         checkIndex: 2,
                         childrens: [],
                     },
                     {
    
    
                        id: 7,
                         checkIndex: 2,
                         name: "测试2级2",
                         childrens: [],
                     }],
                 }],
            }],
            nowIndex: 0,
            columnIndex: [], // 列下标
        };
    },
    methods:{
    
    
    	 back(item) {
    
    }
    }
     components: {
    
    
        Menu,
    }
};
</script>

猜你喜欢

转载自blog.csdn.net/qq_25992675/article/details/108645333