递归组件组合拳,无惧页面嵌套

介绍

递归组件在组件内嵌套组件时比较常用,我在这里举几个例子:

1、后台管理系统的menu菜单

2、教育系统的题目列表

在遍历生成基础题时,遇到了综合题,综合题包含了所有基础题,此时就不用再写一遍基础题,直接调用自身组件即可,这样不论基础题内部嵌套多少层综合题,都可以生成题目列表。


如何实现递归组件?

父页面:正常引入组件

javascript 复制代码
// 父页面
<template>
    <div>
        <Circulation :dataInfo="dataInfo"/>
    </div>
</template>
 
<script>
import Circulation from '@/views/circulation.vue'
export default {
    components: { Circulation },
    data() {
        return {
          dataInfo: [
            // ......
          ]
        }
    },
}
</script>

子组件

javascript 复制代码
// circulation页面
<template>
    <div>
       <div v-for="item in dataInfo"></div>
        // 其它逻辑......

        // 假如遇到children -> 复用自身 
        <Circulation :dataInfo="item.children"/>
    </div>
</template>
 
<script>
export default {
    name: 'Circulation', // 一定要设置name,于组件名相同
    props: {
        dataInfo: {
            type: Array,
            default: () => {
                return []
            }
        },
    },
}
</script>

上面的代码就实现了递归组件,在子组件中不需要引入自身,只需要设置name,然后通过name复用组件即可 下面是你在教育类型项目中会遇到的场景:


注意点

1、事件冒泡

注意:递归组件的事件一定要用.stop阻止冒泡,否则会报错 例如:@click.stop="onClose(item)"

2、prop值更新

在递归组件中通过事件更改prop的值时,会报错,提示请避免在子组件中对prop进行直接更改 Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "questionList" 避免直接更改 prop,因为每当父组件重新渲染时,该值都会被覆盖。相反,请使用基于道具值的数据或计算属性。被变异的道具:"questionList" 递归组件尽量避免直接对prop进行修改,哪怕你使用了计算属性,也会报错提示。

3、递归组件深层事件

由于是递归组件,层级的嵌套可能会很深,但是页面只有当前这一个,如果只处理当前层级的逻辑可以直接@click.stop="xxx"触发 如果需要将事件向父级回传,则需要使用emit,并且自身页面的递归组件上也需要设置事件,例如:

javascript 复制代码
// 父页面
<template>
    <div>
        <Circulation :dataInfo="dataInfo" @onChange="onChange"/>
    </div>
</template>
<script>
import Circulation from '@/views/circulation.vue'
export default {
    components: { Circulation },
    data() {
        return {
          dataInfo: [
            // ......
          ]
        }
    },
    methods: {
      // 触发事件 
      onChange() {},
    }
}
</script>

子页面

javascript 复制代码
// circulation页面
<template>
    <div>
       <div v-for="item in dataInfo"></div>
        // 其它逻辑......

        // 假如遇到children -> 复用自身 
        <Circulation :dataInfo="item.children"  @onChange="onChange"/>
    </div>
</template>
 
<script>
export default {
    name: 'Circulation', // 一定要设置name,于组件名相同
    props: {
        dataInfo: {
            type: Array,
            default: () => {
                return []
            }
        },
    },
    methods: {
      // 触发回传
      onChange() {
        this.$emit('onChange')
      },
    }
}
</script>

这样做它的回传事件会层层递归,直到返回最上层。 在渲染层面,它是层层递。 在事件回传层面,它是层层归。


如果觉得该组件不错,欢迎点赞👍、收藏💖、转发✨哦~

阅读其它:

微信小程序用户隐私API(👈点击直达)

前端换肤,聊一聊主题切换那些事(👈点击直达)

Shapes布局-文字环绕动画(👈点击直达)

css绘制一个Pinia小菠萝(👈点击直达)

深入理解Promise(👈点击直达)

相关推荐
前端一课几秒前
【vue高频面试题】第 13 题:Vue 的 `nextTick` 原理是什么?为什么需要它?
前端·面试
前端一课几秒前
【vue高频面试题】第 12 题:Vue(尤其 Vue3)中父子组件通信方式有哪些?区别是什么?
前端·面试
前端一课3 分钟前
解释watch和computed的原理
前端·面试
前端一课5 分钟前
【vue高频面试题】第 18 题:Vue3 响应式原理中的 effect、依赖收集与依赖触发
前端·面试
前端一课5 分钟前
【vue高频面试题】第 19 题:Vue3 性能优化技巧
前端·面试
前端一课8 分钟前
【vue高频面试题】第 15 题:computed vs watch 区别 + 使用场景
前端·面试
前端一课8 分钟前
【vue高频面试题】第 20 题:Vue3 生命周期 + watch 执行顺序
前端·面试
前端一课8 分钟前
【vue高频面试题】第 16 题:Vue3 响应式原理深度解析(Proxy + effect 栈 + 依赖追踪)
前端·面试
执笔论英雄12 分钟前
【大模型推理】小白教程:vllm 异步接口
前端·数据库·python
炒毛豆12 分钟前
vue3+ant design vue实现表单验证失败后,自动滚动到失败的位置(scrollToField)
前端·javascript·vue.js