因为项目一些数据需要树形展示,但是官网组件没有。现在简单封装一个组件在app中使用,可以无线嵌套,展开,收缩,获取子节点数据等。
简单效果
组件TreeData
<template>
<view class="tree">
<template v-for="(node, index) in treeData">
<view>
<span @click="toggleNode($event, node)">
<uni-icons
v-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>
凑活用