vue中的递归组件实现树结构

效果图

展示图

组件说明

此组件为一个递归组件,实现页面树结构,app上建议树结构最多为3层,否则难以展示数据

基本使用

<m-tree :load="loadNode"></m-tree>

loadNode(node, resolve) {
	//console.log(node);

	if (node == null) {

		setTimeout(() => {
			//第一次调用
			let res = [{
				id: 1,
				text: '公司1',
				isExistChildNode: true, //是否存在子节点
				extra: {
					usercode: '00000001',
					prjid: '1234567890'
				} //额外的参数
			}, {
				id: 2,
				text: '公司2',
				isExistChildNode: false, //是否存在子节点
				extra: {
					usercode: '00000002',
					prjid: '1234567890'
				} //额外的参数
			}]
			return resolve(res);
		}, 1000)

	} else {
		if (node.isExistChildNode) {
			setTimeout(() => {
				//开始递归
				let res = [{
					id: 11,
					text: '部门1',
					isExistChildNode: false, //是否存在子节点
					extra: {
						usercode: '00000011',
						prjid: '1234567890'
					} //额外的参数
				}, {
					id: 12,
					text: '部门2',
					isExistChildNode: false, //是否存在子节点
					extra: {
						usercode: '00000012',
						prjid: '1234567890'
					} //额外的参数
				}]
				return resolve(res);
			}, 1000);
		} else {
			return resolve(null);
		}

	}


}

Props

参数 说明 类型 默认值 可选值
load 回调函数 Function 必填 -
nodeItem 节点数据 Object null -
leavl 树的层级 Number 1,从1开始算层级 -

Events

事件名称 说明 回调参数
select 选择数据项 e{};nodeItem节点数据

组件实现

<!--  -->
<template>
	<view class="m-tree">
		<view class="node" v-for="(item,index) in treeList" :key="index">
			<view class="item">
				<view class="left" @click="tapShowNode(item)">
					<text v-if="item.isExistChildNode&&item.showChildren" class="icondemo demo-jianqu left-icon"></text>
					<text v-else-if="item.isExistChildNode" class="icondemo demo-jia left-icon"></text>
				</view>
				<view class="right" @click="tapSelect(item)">
					<text>{{item.text}}</text>
				</view>
			</view>
			
			<m-tree v-if="item.showChildren" :nodeItem="item" :leavl="(leavl+1)" :load="load"></m-tree>
		</view>

	</view>
</template>

<script>
	import {bus} from '@/libs/bus.js';
	export default {
		name:"m-tree", //递归组件必须有name属性,要不找不到注册组件
		props: {
			load: {
				type: Function,
				required: true
			},
			nodeItem: {
				type: Object,
				// 对象或数组默认值必须从一个工厂函数获取
				default: function() {
					return null
				}
			},
			leavl: {
				type: Number,
				default: 1 //层级
			}
		},
		data() {
			return {
				treeList: []
			}
		},
		created() {
			let that = this;
			this.load(this.nodeItem, (data) => {
				
				if (data != null) {
					data.forEach((item) => {
						item.showChildren = false;
						item.leavl = that.leavl;
					});
					this.treeList = data;
					//console.log(data);
				} else {
					this.treeList = [];
				}
			});
		},
		//页面渲染完成
		mounted() {

		},
		watch: {

		},
		/**
		 * 计算属性
		 */
		computed: {

		},
		methods: {
			tapSelect(item){
				//console.log(item);
				bus.$emit('select',item);
			},
			tapShowNode(item){
				item.showChildren = !item.showChildren;
				
			}
		}
	}
</script>

<style lang="scss" scoped>
	.m-tree {
		padding-left: 20rpx;

		.node {
			.item {
				padding: 30rpx 20rpx 30rpx 0;
				display: flex;
				align-items: center;
				border-bottom: 1px solid #F2F6FC;

				.left {
					width: 100rpx;
					display: flex;
					justify-content: center;

					.left-icon {
						color: #409EFF;
						font-size: 48rpx;
					}
				}

				.right {
					width: 400rpx;
					font-size: 32rpx;
				}
			}
		}
	}
</style>

补充说明

  1. 递归组件不能使用this.$emit('select',item);来给父组件传值了,因为子组件中即存在子组件又存在父组件,可以通过EventBus来监听

  2. 使用方法

//引用
import {
	bus
} from '@/libs/bus.js';

//父组件中监听
onLoad() {
	bus.$on('select', e => {
		console.log(e);
	})
},
//引用
import {
	bus
} from '@/libs/bus.js';

//子组件传值
tapSelect(item){
	//console.log(item);
	bus.$emit('select',item);
},

//bus.js文件

import Vue from "vue"

export const bus=new Vue();
  1. 递归组件必须有name属性,要不找不到注册组件
posted @   迎风而笑  阅读(1394)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示