因为项目一些数据需要树形展示,但是官网组件没有。现在简单封装一个组件在app中使用,可以无线嵌套,展开,收缩,获取子节点数据等。
简单效果
组件TreeData
<template><view class="tree"><template v-for="(node, index) in treeData"><view><span @click="toggleNode($event, node)"><uni-iconsv-if="node.children && node.children.length > 0":type="node.expanded ? 'arrowdown' : 'arrowright'"size="14"></uni-icons>{{ node.label }}</span><span@click.stop="deleteNode($event, node)"class="action-button delete-button">删除</span><span@click.stop="editNode($event, node)"class="action-button edit-button">编辑</span><view v-if="node.expanded" class="children"><Tree:treeData="node.children"@edit-node="(childNode) => $emit('edit-node', childNode)"@delete-node="(childNode) => $emit('delete-node', childNode)"/></view></view></template></view>
</template><script>
export default {name: "Tree",props: {treeData: {type: Array,default: () => [],},expandAll: {type: Boolean,default: true,},},data() {return {init: false,};},watch: {treeData: {immediate: true,handler(newData) {if (!this.init) {this.initializeTreeData(newData, this.expandAll);this.init = true;}},},},methods: {initializeTreeData(nodes, expanded) {nodes.forEach((node) => {this.$set(node, "expanded", expanded); // 使用 $set 确保响应式if (node.children && node.children.length > 0) {this.initializeTreeData(node.children, expanded); // 递归处理子节点}});},toggleNode(event, node) {event.stopPropagation(); // 阻止事件冒泡node.expanded = !node.expanded; // 切换节点展开状态},editNode(event, node) {event.stopPropagation();this.$emit("edit-node", node); // 触发父组件的 edit-node 事件,并传递当前节点},deleteNode(event, node) {event.stopPropagation();this.$emit("delete-node", node); // 触发父组件的 delete-node 事件,并传递当前节点},},
};
</script><style scoped>
.tree {padding-left: 15px;
}
.children {padding-left: 15px;
}
.tree-node {display: flex;align-items: center;
}.action-button {cursor: pointer;margin-left: 10px;color: #409eff;
}.edit-button {float: right;
}.delete-button {float: right;
}
</style>
在页面中使用...
<template><view class="page"><Tree:treeData="treeData":expandAll="expandAll"@edit-node="handleEditNode"@delete-node="handleDeleteNode"/></view>
</template><script>
import Tree from "@/components/TreeData";export default {components: {Tree,},data() {return {treeData: [{label: "根节点 1",children: [{label: "子节点 1-1",children: [{label: "子节点 1-1-1",children: [],},{label: "子节点 1-1-2",children: [],},],},{label: "子节点 1-2",children: [],},],},{label: "根节点 2",children: [{label: "子节点 2-1",children: [],},],},],expandAll: true, // 控制是否全部展开};},methods: {handleEditNode(node) {console.log("编辑节点", node);// 处理编辑节点的逻辑},handleDeleteNode(node) {console.log("删除节点", node);// 处理删除节点的逻辑},},
};
</script><style scoped>
page {background-color: #f5f6f8;
}.page {padding: 20px;
}
</style>
凑活用