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>
补充说明
-
递归组件不能使用this.$emit('select',item);来给父组件传值了,因为子组件中即存在子组件又存在父组件,可以通过EventBus来监听
-
使用方法
//引用
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();
- 递归组件必须有name属性,要不找不到注册组件
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通