场景: 点击一级目录,展开他的子内容,可能子内容还有子内容,在不知道多少级的情况下使用递归可以完美解决这个问题。
假设一个数据结构是:
treeData :[
{
name:'zs',
code:1,
children:[
{
name:'zss',
code:01,
children:[
{
name:'zsss',
code:001,
children:[
// 也可能还有孩子
]
}
]
}
]
},
{
// 和第一个对象一样的结构这里不多写了
}
]
那么,递归无非就是有相同的结构循环的调用,那么我们定义一个组件叫Tree
Index.vue
import Tree from ''./Tree.vue' // 引入要递归的组件Tree
// 看一下应用
<template>
<Tree
v-for="tree in treeData " //这相当于循环调用tree组件了,但是只是第一层的,每个tree只是个数组里面的大对象
:key="tree.code" // 每次需要个单独的key
:treeList="tree" // 传给Tree组件的值,用来绘制页面
></Tree>
</template>
Tree.vue
// 接收参数
export default {
name:'Tree' // 注意,这个名字一定要起,通过这个名字找到这个组件
props:{
treeList:{
type:Object,
default:() => {
return {}
}
}
}
}
// 应用,也就是绘制页面
<template>
// 这前面可以添加按钮,来控制每级目录的开合,开合可以在数据中定义一个属性来控制这里我就不写了
<span>{{treeList.name}}</span> // 这是一级目录的名称
<Tree
v-for="item in treeList,children" // 这就是递归数据里面children的逻辑,循环childrend数组,然后把每项再传给这个Tree,看他是否还有children
:treeList="item"
:key="item.code"
>
</Tree>
</template>
1 如果说选中或取消当前的父级,他的所有递归的子集都会被选中或取消
selectItem(item) {
this.$set(item,'checked',!item.checked) // 父级点击的时候改变选中状态
if(item.children && item.children.length > 0) {
this.getChild(item.children,item.checked) // 把点击的状态传给他的子集
}
}
getChild(child,status) {
data.map((item) => {
this.$set(item,'checked',status) // 把点击的父级的第一级子集都设成和父级一样的状态
if(item.children && item.children.length > 0) { // 如果此级还有子集,就再掉这个方法,就会达到递归的效果
this.getChild(item.children,status)
}
})
}
2 当如果没有选择父级,而是把子集都选中了,那么父级也要变成选中,而且当父级选中,取消了一个其中的子集,那么父级也要取消选中
changeParent(item) {
let n = item.level // 这是点击当前元素的级数,可以遍历数据的时候自己定义一个变量获取一下
ket parentString = '';
let parentArr = [];
for(let i=1;i<n;i++) {
parentString +=".$parent"
let parentJson = "this" + parentString + ".treeList"
parentArr .push(parentJson ) // 里面的数据大致是['this.$parent.treeList','this.$parent.$parent.treeList',..........],模拟出有n级元素的所有父级
}
for(let j=0;j<parentArr.length;j++) {
let curParent = eval(parentArr[j]) // 把字符串变成他本身含义的js代码
if(curParent .children) {
let isChecked = curParent .children.every((i) => i.checked) // 如果他的孩子都是选中的返回true,否则返回false
this.$set(curParent ,'checked',isChecked ) //给他的父级设置状态
}
}
}
添加:
递归的数据结构下给数据加层级标志
// data是传进来要处理的数组,level默认传1
setLayer(data, level) {
if (!data) {
return;
}
data.forEach((item) => {
item.levelIndex = level;
if (item.children && item.children.length > 0) {
//如果提示有子级
item.children.forEach(() => {
this.setLayer(item.children, level + 1);
});
}
});
return data;
},