1. 程式人生 > 其它 >vue中的遞迴元件實現樹結構

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屬性,要不找不到註冊元件