写点什么

一个可递归遍历的 Vue 树型组件

用户头像
空城机
关注
发布于: 2021 年 04 月 13 日
一个可递归遍历的Vue树型组件

在创建列表时,常常会遇到一层套一层,如同套娃一般的列表结构。这样的列表结构其实对于我来说还是挺麻烦的,经常需要一层层的写。(一般而言的结构三层应该是最多了,但是遇到特殊情况可能就不止了


那么遇到列表不同层的数据结构类似的情况,是不是可以使用递归的方法来创建一个组件呢。

接下来做一下尝试:需要变成列表的数据

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
用户头像

空城机

关注

曾经沧海难为水,只是当时已惘然 2021.03.22 加入

业余作者,在线水文 主要干前端的活,业余会学学python 欢迎各位关注,互相学习,互相进步

评论

发布
暂无评论
一个可递归遍历的Vue树型组件