uni-app学习笔记(树状数组以及转换)

树状数组

<template>
	<view class="content">
		<view class="mix-tree-list">
			<block v-for="(item, index) in treeList" :key="index">
				
				<!-- <van-swipe-cell :right-width="155"> -->
					<view 
						class="mix-tree-item"
						:style="[{
								paddingLeft: item.rank*15 + 'px',
								zIndex: item.rank*-1 +50
							}]"
						:class="{
								border: treeParams.border === true,
								show: item.show,
								last: item.lastRank,
								showchild: item.showChild
							}"
					>
							<view @click.stop="treeItemTap(item, index)">
								<image class="mix-tree-icon" :src="item.lastRank ? treeParams.lastIcon : item.showChild ? treeParams.currentIcon : treeParams.defaultIcon"></image>
								{{item.name}}
							</view>
							<view class="total-cell" v-if="allowUpdate=='允许'">
							  	<view class="van-cell">
							  	</view>
								<view class="van-cell">
								</view>
							  	<view class="van-cell">
							  	</view>
							</view>
					</view>
					<!-- </van-swipe-cell> -->
				</van-swipe-cell>
			</block>
		</view>
	</view>
</template>

<script>
	export default {
		props: {
			list: {
				type: Array,
				default(){
					return [];
				}
			},
			params: {
				type: Object,
				default(){
					return {}
				}
			},
			allowUpdate: {
				type: String,
				default: '不允许'
			}
		},
		data() {
			return {
				treeList: [],
				treeParams: {
					defaultIcon: '/static/mix-tree/defaultIcon.png',
					currentIcon: '/static/mix-tree/currentIcon.png',
					lastIcon: '',
					border: false
				}
			}
		},
		watch: {
			list(list){
				
				this.treeParams = Object.assign(this.treeParams, this.params);
				console.log(this.treeParams, this.params);
				this.renderTreeList(list);
			}
		},
		methods: {
			/**
			 * 添加树节点
			 */
			addTree(item){
				console.log(item);
			},
			//扁平化树结构
			renderTreeList(list=[], rank=0, parentId=[]){
				list.forEach(item=>{
					this.treeList.push({
						id: item.id,
						name: item.name,
						sortNum: item.sortNum,
						children: item.children, // 它的子节点
						parentId,  // 父级id数组
						rank,  // 层级
						showChild: false,  //子级是否显示
						show: rank === 0  // 自身是否显示
					})
					if(Array.isArray(item.children) && item.children.length > 0){
						let parents = [...parentId];
						parents.push(item.id);
						this.renderTreeList(item.children, rank+1, parents);
					}else{
						this.treeList[this.treeList.length-1].lastRank = true;
					}
				})
			},
			// 点击
			treeItemTap(item){
				let list = this.treeList;
				let id = item.id;
				if(item.lastRank === true){
					//点击最后一级时触发事件
					this.$emit('treeItemClick', item);
					return;
				}
				item.showChild = !item.showChild;
				list.forEach(childItem=>{
					if(item.showChild === false){
						//隐藏所有子级
						if(!childItem.parentId.includes(id)){
							return;
						}
						if(childItem.lastRank !== true){
							childItem.showChild = false;
						}
						childItem.show = false;
					}else{
						if(childItem.parentId[childItem.parentId.length-1] === id){
							childItem.show = true;
						}
					}
				})
			}
		}
	}
</script>

<style>
	.mix-tree-list{
		display: flex;
		flex-direction: column;
		padding-left: 30upx;
	}
	.mix-tree-item{
		display: flex;
		align-items: center;
		font-size: 30upx;
		color: #333;
		height: 0;
		opacity: 0;
		transition: .2s;
		position: relative;
	}
	.mix-tree-item.border{
		border-bottom: 1px solid #eee;
	}
	.mix-tree-item.show{
		height: 80upx;
		opacity: 1;
	}
	.mix-tree-icon{
		width: 26upx;
		height: 26upx;
		margin-right: 8upx;
		opacity: .9;
	}
	
	.mix-tree-item.showchild:before{
		transform: rotate(90deg);
	}
	.mix-tree-item.last:before{
		opacity: 0;
	}
	/* 自加 */
	.total-cell{
		display: flex;
	}
	.van-cell{
		/* padding-top: 18rpx; */
	}
</style>

调用(包含父子关系数组转换成树状结构)

<template>
	<view class="content">
		<!-- 导航栏 -->
		<!-- #ifdef APP-PLUS -->
		<view style="padding-bottom: 60px;">
			<van-nav-bar
			  title="个人信息"
			  left-text="返回"
			  left-arrow
			  :fixed="true"
			   z-index="999"
			  @click-left="$navigateBack(1)"
			/>
		</view>
		<!-- #endif -->
		<view class="topAdd">
			<vant-btn type="info" size="small">添加主目录</vant-btn>
		</view>
		<mix-tree
			:list="list" 
			:params="treeParams"
			@treeItemClick="treeItemClick" 
			:allowUpdate="allowUpdate"
		></mix-tree>
	</view>
</template>

<script>
	var that;
	import mixTree from '@/components/mix-tree/mix-tree';
	export default {
		components: {
			mixTree
		},
		props:["allowUpdate"],
		data() {
			return {
				list: [],
				treeParams: {
					defaultIcon: '/static/i2.png', // 默认图标
					currentIcon: '/static/i1.png', // 展开图标
					lastIcon: '/static/i3.png', //最后一级图标
					border: true   // 边框, 默认不显示
				}
			}
		},
		methods: {
			/* 落地页获取 */
			getSiteGroundPage(pageData) {
				that.$showLoading();
				/* 保存原始数组 */
				
				var data = {
					rows: 1000,
					page: 0,
					sortName: "sortNum",
					sortOrder: "asc"
				};
				that.$http.post(that.webRoot.host+that.webRoot.siteGroundPage.getTotalGroup,
				pageData || data,
				{
					headers:{
						'content-type':that.webRoot.header.contentType,
						'Authorization': 'bearer '+uni.getStorageSync('access_token'),
						'deviceId' : that.UUID
					},
				}).catch(function(response){
					uni.hideLoading();
					console.log(response);
					if(response.status==200){
						that.list = that.getList(response.data.content);
						console.log(that.list);
					}else{
						uni.showToast({
							title: response.message,
							icon:'none'
						});
					}
				})
			},
			getList(data) {
				 //没有父节点的数据
				  let parents = data.filter(value => value.parentId == 'undefined' || value.parentId == null)
				 
				  //有父节点的数据
				  let children = data.filter(value => value.parentId !== 'undefined' && value.parentId != null)
				 
				  //定义转换方法的具体实现
				  let translator = (parents, children) => {
				    //遍历父节点数据
				    parents.forEach((parent) => {
				      //遍历子节点数据
				      children.forEach((current, index) => {
				        //此时找到父节点对应的一个子节点
				        if (current.parentId === parent.id) {
				          //对子节点数据进行深复制,这里只支持部分类型的数据深复制,对深复制不了解的童靴可以先去了解下深复制
				          let temp = JSON.parse(JSON.stringify(children))
				          //让当前子节点从temp中移除,temp作为新的子节点数据,这里是为了让递归时,子节点的遍历次数更少,如果父子关系的层级越多,越有利
				          temp.splice(index, 1)
				          //让当前子节点作为唯一的父节点,去递归查找其对应的子节点
				          translator([current], temp)
				          //把找到子节点放入父节点的children属性中
				          typeof parent.children !== 'undefined' ? parent.children.push(current) : parent.children = [current]
				        }
				      }
				      )
				    }
				    )
				  }
				 
				  //调用转换方法
				  translator(parents, children)
				 
				  //返回最终的结果
				  return parents
			},
			//点击最后一级时触发该事件
			treeItemClick(item) {
				let {
					id,
					name,
					parentId
				} = item;
				uni.showModal({
					content: `点击了${parentId.length+1}级菜单, ${name}, id为${id}, 父id为${parentId.toString()}`
				})
				console.log(item)
			}
		},
		created() {
			that = this;
			that.getSiteGroundPage();
		},
	}
</script>

<style lang="scss">
	.content{
		.topAdd{
			padding: 2vh;
		}
	}
</style>

树状结构拆分成父子节点数组(用于展开与收缩,致谢-----庄哥)

<template>
	<view>
		<view v-for="(item, index) in list" :key="index" :style="{marginLeft: (item.level - 1) * 20 + 'rpx'}" class="list-item"
		 v-show="item.show" @tap="showChildren(index)">
			{{item.name}}
		</view>
	</view>
</template>
<script>
	export default {
		components: {},
		data() {
			return {
				dataList: [{
					"addDate": 1551926856000,
					"id": 36,
					"name": "西藏",
					"siteId": 80,
					"sortNum": 2,
					"updateDate": 1551926856000,
					"children": [{
						"addDate": 1579073689000,
						"id": 942,
						"name": "111",
						"parentId": 36,
						"siteId": 80,
						"sortNum": 6,
						"updateDate": 1579073689000,
						"children": [{
							"addDate": 1579137342000,
							"id": 943,
							"name": "22",
							"parentId": 942,
							"siteId": 80,
							"sortNum": 7,
							"updateDate": 1579137342000,
							"text": "22"
						}],
						"text": "111"
					}],
					"text": "西藏"
				}, {
					"addDate": 1551926847000,
					"id": 35,
					"name": "张家界",
					"siteId": 80,
					"sortNum": 1,
					"updateDate": 1551926847000,
					"children": [{
						"addDate": 1584589492000,
						"id": 945,
						"name": "天门山",
						"parentId": 35,
						"siteId": 80,
						"sortNum": 8,
						"updateDate": 1584589492000,
						"children": [{
							"addDate": 1584589522000,
							"id": 946,
							"name": "玻璃桥",
							"parentId": 945,
							"siteId": 80,
							"sortNum": 9,
							"updateDate": 1584589522000,
							"children": [{
								"addDate": 1584589528000,
								"id": 947,
								"name": "安全组",
								"parentId": 946,
								"siteId": 80,
								"sortNum": 10,
								"updateDate": 1584589528000,
								"text": "12"
							}],
							"text": "12"
						}],
						"text": "42"
					}],
					"text": "张家界"
				}, {
					"addDate": 1551926847000,
					"id": 35,
					"name": "苏州",
					"siteId": 80,
					"sortNum": 1,
					"updateDate": 1551926847000,
				}],
				list: [],
			}
		},
		onLoad() {
			var list = [];
			try {
				this.getList(this.dataList, 1);
			} catch (err) {
				console.log(err)
			}
		},
		methods: {
			// 递归获取子元素

			getList(data, level) {
				for (let d_item of data) {
					const item = {
						id: d_item.id,
						name: d_item.name,
						parentId: d_item.parentId,
						show: level === 1,
						level,
						counts: d_item.children ? d_item.children.length : 0, // 子元素数量
					}
					this.list.push(item);
					if (d_item.children && d_item.children.length > 0) {
						this.getList(d_item.children, level + 1);
					}
				}
			},
			// 折叠
			showChildren(ind) {
				let {
					list
				} = this;
				if (list[ind].counts === 0) return;
				for (let i = ind + 1; i < list.length; i++) {
					if (list[i].show) {
						if (list[i].level > list[ind].level) {
							list[i].show = false;
						}
					} else {
						if (list[i].level === list[ind].level + 1) {
							list[i].show = true;
						}
					}
					if (list[i].level <= list[ind].level) {
						break;
					}
				}
				this.list = list;
			}
		},
	}
</script>
<style>
	.list-item {
		padding: 20rpx 0;
	}
</style>

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值