开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 15 天,点击查看活动详情
曾经遇到一个需要使用递归组件的场景:在页面中动态生成规则,不限制嵌套层级。类似这种结构的还有树形,当可以无限增加子结点时,可以用递归来实现。
递归的核心就是自己调用自己,在代码中组件的递归就是组件自己调用自己,不需要设计得太复杂即可以实现。
设计思路
基础组件的形式如下:
- 每次新增条件,都是在当前容器内添加一行条件配置
- 新增子分组:在当前容器内新增一个子容器(这里就需要进行递归了)
- 数据:
- 递归组件需要共享同一个数据
- 条件和分组需要区分类型,方便后面递归内容的展示
代码实现
主页面
<RuleBox :object="object"></RuleBox>
子组件
- 工具栏部分:
<div>
<el-select v-model="object.rules">
<el-option label="且" value="and"/>
<el-option label="或" value="or"/>
</el-select>
<el-button @click="add">新增条件</el-button>
<el-button @click="addChildern">新增子分组</el-button>
</div>
- 条件选项及组件递归:
组件自己调用自己,不需要单独注册组件
<template v-for="(item, index) in object.list">
<el-row v-if="item.type === 'condition'">
<el-select v-model="item.select1">
<el-option label="字段1" value="1"/>
</el-select>
<el-select v-model="item.symbol">
<el-option label="等于" value=""/>
</el-select>
<el-select v-model="item.select2">
<el-option label="字段1" value="1"/>
</el-select>
<el-button @click="hadelDelete(index)">删除</el-button>
</el-row>
<el-row v-if="item.type === 'group' && item.list.length > 0">
<rule-box :object="item"></rule-box>
</el-row>
</template>
- 函数实现
添加条件和添加分组的区别就在于,添加分组需要在数据中有一层子条件的嵌套关系:
注:子容器中 list 字段的长度为 0 的时候,表示容器为空,即为子容器消失的条件,不需要额外为整个容器添加删除按钮
item.type === 'group' && item.list.length > 0
- 数据结构
最终的数据结构如下:
组件传递自定义参数
在递归组件的场景中,可能会在某一层的下拉框或是其他组件操作时对数据进行处理,触发 @change 事件时传递一些自定义参数,而组件也默认携带了部分参数,如果想同时传递,有如下两种方法:
-
在模板中使用 this.函数名.bind(this,其它参数)
@change={ this.onChange.bind(this,'自定义参数') } -
在模板中直接使用箭头函数,将 value 和自定义参数传入
@change={ value => { this.onChange(value,'自定义参数')} }