前段时间要做一个树状递归的展开组件,原来都是用的第三方框架直接用,突然要用一个自定义能力比较强的,就想着看看有没有写的差不多的自己改一下得了,结果用某度搜了一下,清一色复制粘贴的文章,而且也写的极其简单。。。干脆还是自己撸得了。
效果图
不多说直接上代码吧。
如何引用组件
<template>
<div style="width: 300px">
<tree :treeArr="dataArr"></tree>
</div>
</template>
<script>
import tree from "./tree.vue";
export default {
components: {
tree,
},
data() {
return {
dataArr: [],
};
},
mounted() {
this.dataArr = [
{
name: "广东",
isShow: false,
level: 1,
children: [
{
name: "广州",
isShow: false,
level: 2,
children: [
{
name: "天河区",
level: 3,
isShow: false,
children: [],
},
{
name: "黄埔区",
level: 3,
children: [],
},
{
name: "荔湾区",
level: 3,
children: [],
},
],
},
{
name: "深圳",
level: 2,
isShow: false,
children: [],
},
{
name: "佛山",
level: 2,
isShow: false,
children: [],
},
],
},
{
name: "湖北",
isShow: false,
level: 1,
children: [
{
name: "武汉",
level: 2,
children: [],
},
],
},
];
},
};
</script>
组件 tree
-
组件中需要注意的几点:
-
v-show="item.children && item.children.length"这个是递归组件的终止条件,如果没有停止条件就会陷入死循环,而且由于你会频繁的打开隐藏,所以就不要用v-if了,应该使用v-show; -
添加动画效果时,如果你的高度不确定,应该使用
max-height,但是数值不应该设置太大,否则会有很明显的卡顿效果,最好是估测一个和实际值差不多的高度,或者自行计算也可以。
-
<template>
<div class="container" :style="{ 'max-height': isShow ? '500px' : 0 }">
<div v-for="(item, index) in treeArr" :key="item.name">
<div
class="container-item"
@click="handleOpenChildren(index)"
:style="{transform: `translateX(${(item.level-1)*10}px)`}" //做一个偏移来显示层次
>
<img
class="item-img"
:src="
item.isShow
? '../../../static/close.png'
: '../../../static/open.png'
"
/>
<span>{{ item.name }}</span>
</div>
//递归组件的终止条件
<div v-show="item.children && item.children.length">
<tree :treeArr="item.children" :isShow="item.isShow"></tree>
</div>
</div>
</div>
</template>
<script>
export default {
name: "tree", //递归组件的使用:定义name属性,就可以在当前文件中直接使用组件。(多提一句在uni-app中小程序使用递归组件还需要引用自己并在components中注册)
props: {
treeArr: Array,
isShow: {
type: Boolean,
default: true,
},
},
data() {
return {
arr: [],
};
},
methods: {
handleOpenChildren(index) {
let data = this.treeArr[index];
if (data.children && data.children.length) {
data.isShow = !data.isShow;
} else {
// 如果数据特别多,使用了懒加载,此处需要请求接口添加数据
}
},
},
};
</script>
<style>
.container {
overflow: hidden;
transition: 0.5s all;
}
.container-item {
line-height: 30px;
font-size: 15px;
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
}
.item-img {
height: 15px;
width: 15px;
margin: 0 20px;
}
</style>
如果各位发现有什么错误和需要改进的地方还希望多多指出,谢谢各位