一个可递归遍历的 Vue 树型组件
发布于: 2021 年 04 月 13 日
序
在创建列表时,常常会遇到一层套一层,如同套娃一般的列表结构。这样的列表结构其实对于我来说还是挺麻烦的,经常需要一层层的写。(一般而言的结构三层应该是最多了,但是遇到特殊情况可能就不止了)
那么遇到列表不同层的数据结构类似的情况,是不是可以使用递归的方法来创建一个组件呢。
接下来做一下尝试:需要变成列表的数据
options: [
{
value: 1,
label: '东南',
children: [{
value: 2,
label: '上海',
children: [
{ value: 3, label: '普陀' },
{ value: 4, label: '黄埔' },
{ value: 5, label: '徐汇' }
]
}, {
value: 7,
label: '江苏',
children: [
{ value: 8, label: '南京' },
{ value: 9, label: '苏州' },
{ value: 10, label: '无锡' }
]
}, {
value: 12,
label: '浙江',
children: [
{ value: 13, label: '杭州' },
{ value: 14, label: '宁波' },
{ value: 15, label: '嘉兴' }
]
}]
}, {
value: 17,
label: '西北',
children: [{
value: 18,
label: '陕西',
children: [
{ value: 19, label: '西安',
children: [{
value: 19,
label: '陕西',
children: [
{ value: 30, label: '西安' },
{ value: 40, label: '延安' }
]
}, {
value: 41,
label: '新疆维吾尔族自治区',
children: [
{ value: 42, label: '乌鲁木齐' },
{ value: 43, label: '克拉玛依' }
]
}]
},
{ value: 20, label: '延安' }
]
}, {
value: 21,
label: '新疆维吾尔族自治区',
children: [
{ value: 22, label: '乌鲁木齐' },
{ value: 23, label: '克拉玛依' }
]
}]
}]
复制代码
效果
递归实现的列表
分析
从数据开始着手分析,在这份数据当中,层级较多,但是每一层中的对象都有自身的 value 值和 label 值,以及可能存在的 children 子层级数组对象。
可以先创建一个组件 treeVue,treeVue 组件通过 props 获取到父组件传递过来的列表数据。
通过分析每一层的各个元素,使用 $set 给元素添加一个 showflag 属性,这个属性控制其子层级的显隐
var treeVue = {
name:'treevue',
template: "#treevue",
props: ['datavalue'],
data: function() {
return {
options:'', //获取到的数据
}
},
mounted: function() {
var self = this;
this.options = this.datavalue;
$.each(this.options,function(index,item){
self.$set(item, 'showflag', true)
})
},
watch: {},
methods: {
},
filters:{
textshow:function(str,flag){
if(flag) {
if(str)
return " -- 显示";
else
return " -- 隐藏";
} else {
return ""
}
}
}
}
复制代码
在 HTML 中 treeVue 组件
<div class="tree-vue" >
<div class="treefirst" v-for="(item1,index1) in datavalue" :key='index1' >
<div class="btn_name" @click.stop="item1.showflag = !item1.showflag"> {{ item1.label }}{{ item1.showflag | textshow(item1.children) }} </div>
</div>
</div>
复制代码
如以上这种方式使用 treevue 组件,只能显示第一层的元素
所以需要在调用的组件中再添加一句<treevue v-show="item1.children && item1.showflag" :datavalue="item1.children" ></treevue>
这样才能够使得组件进行递归
<div class="tree-vue" >
<div class="treefirst" v-for="(item1,index1) in datavalue" :key='index1' >
<div class="btn_name" @click.stop="item1.showflag = !item1.showflag"> {{ item1.label }}{{ item1.showflag | textshow(item1.children) }} </div>
<treevue v-show="item1.children && item1.showflag" :datavalue="item1.children" ></treevue>
</div>
</div>
复制代码
完整代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js" type="text/javascript" charset="utf-8"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<title>vue树型组件</title>
<style type="text/css">
.treefirst{
margin-left: 30px;
}
.treefirst .btn_name {
display: inline-block;
cursor: pointer;
background-color: #1CD8F3;
}
.treefirst .treefirst .btn_name{
background-color: yellow;
}
.treefirst .treefirst .treefirst .btn_name{
background-color: greenyellow;
}
.treefirst .treefirst .treefirst .treefirst .btn_name{
background-color: peachpuff;
}
.treefirst .treefirst .treefirst .treefirst .treefirst .btn_name{
background-color: pink;
}
</style>
</head>
<body>
<div id="app">
<treevue :datavalue="options" ></treevue>
</div>
<!-- 树型图组件 -->
<script id="treevue" type="text/template">
<div class="tree-vue" >
<div class="treefirst" v-for="(item1,index1) in datavalue" :key='index1' >
<div class="btn_name" @click.stop="item1.showflag = !item1.showflag"> {{ item1.label }}{{ item1.showflag | textshow(item1.children) }} </div>
<treevue v-show="item1.children && item1.showflag" :datavalue="item1.children" ></treevue>
</div>
</div>
</script>
<script type="text/javascript">
var treeVue = {
name:'treevue',
template: "#treevue",
props: ['datavalue'],
data: function() {
return {
options:'', //获取到的数据
}
},
mounted: function() {
var self = this;
this.options = this.datavalue;
$.each(this.options,function(index,item){
self.$set(item, 'showflag', true)
})
},
watch: {},
methods: {
},
filters:{
textshow:function(str,flag){
if(flag) {
if(str)
return " -- 显示";
else
return " -- 隐藏";
} else {
return ""
}
}
}
}
var vm = new Vue({
el:'#app',
data:{
options: [
{
value: 1,
label: '东南',
children: [{
value: 2,
label: '上海',
children: [
{ value: 3, label: '普陀' },
{ value: 4, label: '黄埔' },
{ value: 5, label: '徐汇' }
]
}, {
value: 7,
label: '江苏',
children: [
{ value: 8, label: '南京' },
{ value: 9, label: '苏州' },
{ value: 10, label: '无锡' }
]
}, {
value: 12,
label: '浙江',
children: [
{ value: 13, label: '杭州' },
{ value: 14, label: '宁波' },
{ value: 15, label: '嘉兴' }
]
}]
}, {
value: 17,
label: '西北',
children: [{
value: 18,
label: '陕西',
children: [
{ value: 19, label: '西安',
children: [{
value: 19,
label: '陕西',
children: [
{ value: 30, label: '西安' },
{ value: 40, label: '延安' }
]
}, {
value: 41,
label: '新疆维吾尔族自治区',
children: [
{ value: 42, label: '乌鲁木齐' },
{ value: 43, label: '克拉玛依' }
]
}]
},
{ value: 20, label: '延安' }
]
}, {
value: 21,
label: '新疆维吾尔族自治区',
children: [
{ value: 22, label: '乌鲁木齐' },
{ value: 23, label: '克拉玛依' }
]
}]
}]
},
methods:{},
components: {
treevue: treeVue
}
})
</script>
</body>
</html>
复制代码
划线
评论
复制
发布于: 2021 年 04 月 13 日阅读数: 142
版权声明: 本文为 InfoQ 作者【空城机】的原创文章。
原文链接:【http://xie.infoq.cn/article/dce8ea8c4bf568759ff50cf58】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
空城机
关注
曾经沧海难为水,只是当时已惘然 2021.03.22 加入
业余作者,在线水文 主要干前端的活,业余会学学python 欢迎各位关注,互相学习,互相进步
评论