vue2.x递归组件 树形组件
对于一些有规律的DOM结构,如果我们再一遍遍的编写同样的代码,显然代码是比较繁琐和不科学的,而且自己的工作量会大大增加,
那么有没有一种方法来解决这个问题呢?
答案是肯定的,我们可以通过 递归 方式来生成这个结构,当然在 Vue 模板中也是可以实现的,我们可以在 Vue 的组件中调用自己本身,这样就能达到目的。
当然,在 Vue 中,组件可以递归的调用本身,但是有一些条件:
- 该组件一定要有 name 属性
- 要确保递归的调用有终止条件,防止内存溢出
为了方便理解递归组件,我写了一个小小的 Demo:
下面有这样一个数据,我们希望把它做成一个文件树一样的结果:
treeData: {
title: "Web全栈架构师",
children: [
{
title: "Java架构师"
},
{
title: "JS高级",
children: [
{
title: "ES6"
},
{
title: "动效"
}
]
},
{
title: "Web全栈",
children: [
{
title: "Vue训练营",
expand: true,
children: [
{
title: "组件化"
},
{
title: "源码"
},
{
title: "docker部署"
}
]
},
{
title: "React",
children: [
{
title: "JSX"
},
{
title: "虚拟DOM"
}
]
},
{
title: "Node"
}
]
}
]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
先写一个树组件(Item):
<template>
<li>
<!-- 点击折叠展开 -->
<div @click="toggle">
<!-- 显示内容 -->
{{model.title}}
<!-- 显示折叠展开的图标,如果没有下级目录的话,则不显示 -->
<span v-if="isFolder">[{{open?'-':'+'}}]</span>
</div>
<!-- 控制是否显示下级目录 -->
<ul v-show="open" v-if="isFolder">
<!-- 重点代码,调用自身,实现递归,绑定数据 -->
<Item v-for="model in model.children" :model="model" :key="model.title"></Item>
</ul>
</li>
</template>
<script>
export default {
name: "Item",
// 如果想使用此组件,则需要传递的数据
props: {
model: {
type: Object,
required: true
}
},
data() {
return {
// 默认不显示下级目录
open: false
};
},
computed: {
// 控制是否有下级目录和显示下级目录
isFolder() {
return this.model.children && this.model.children.length;
}
},
methods: {
// 点击折叠展开的方法
toggle() {
if (this.isFolder) {
this.open = !this.open;
}
}
}
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
具体代码的功能已在上面注释
注意
再次强调,这个组件必须要含有 name 这个属性,如果没有 name 这个属性会造成控件自身不能调用自身,而且调用的时候最好绑定一个 key 值,因为这个 key 值是唯一的标识
另外需要注意,当递归组件的时候,需要有一个条件来终止递归,在这里使用 v-for 隐形条件终止递归
然后在外部组件引入这个组件,并绑定数据使用,如下:
<template>
<div>
<ul>
<!-- 使用这个组件,并绑定数据 -->
<Item :model="treeData"></Item>
</ul>
</div>
</template>
<script>
// 导入递归组件
import Item from "./views/Item";
export default {
name: "App",
data() {
return {
// 需要实现递归的数据,上面已经给出
treeData: {...
}
};
},
components: {
// 注册组件
Item
}
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
上次更新: 2024/02/20, 17:31:36
- 01
- Node与GLIBC_2.27不兼容解决方案08-19
- 02
- Git清空本地文件跟踪缓存08-13