在现代前端开发中,树形结构(Tree)是一种常见的数据展示方式,广泛应用于目录、菜单、文件系统等场景。本文将介绍一个高效的 Vue 组件 TreeComp,它能够轻松构建和管理树形结构,支持多种模式和自定义配置。
1. 组件简介 TreeComp 是一个基于 Vue 3 的树形结构组件,具有以下特点:
- 支持多种模式:包括目录模式(
catalog)和菜单模式(menu),满足不同场景的需求。 - 灵活的配置:支持自定义节点样式、展开/收起动画、选中状态等。
- 事件驱动:通过事件机制实现节点展开/收起、选中等操作的回调。
- 高性能:采用递归组件和深度优先搜索(DFS)算法,确保在大数据量下的性能表现。
2. 使用场景 TreeComp 组件适用于以下场景:
- 文件管理系统:展示文件夹和文件的层级结构。
- 导航菜单:构建多级菜单,支持展开和收起。
- 组织架构图:展示公司或团队的层级关系。
- 分类目录:如电商网站的商品分类、博客的标签分类等。
3. 核心代码解析
3.1 组件结构 TreeComp 组件由三个主要部分组成:
Tree.vue:根组件,负责渲染整个树形结构。TreeNode.vue:节点组件,负责渲染单个节点及其子节点。index.vue:入口组件,负责接收外部数据并传递给Tree.vue。
3.2 核心功能实现
3.2.1 节点展开/收起 在 TreeNode.vue 中,通过 toggle 方法实现节点的展开和收起。该方法会根据当前节点的状态(是否展开)以及是否有子节点来更新 isExpanded 的值,并通过 emit 事件通知父组件。
4.属性配置
| 属性名 | 描述 | 类型 | 默认值 | 备注 |
|---|---|---|---|---|
| animate | 动画模式 | Enum | expand | collapse -- 伸缩过渡动画, expand -- 渐变过渡动画 |
| mode | 工作模式 | Enum | catalog | catalog -- 目录模式, menu -- 菜单模式 |
| activeBgColor | 选中节点背景颜色 | String | #F7F8FC | 仅 mode = menu时生效 |
| stepValue | 层级左间距(仅 mode = catalog时生效) | Number | 15 | 仅在目录模式下有效 |
| defaultProps | 键值对属性匹配 | Object | {id:"id",children:"children",label:"label"} | 定义数据对象中的键与组件属性的对应关系 |
| arrowClick | 是否点击箭头才展开/收起节点(仅 mode = catalog时生效) | Boolean | false | 仅在目录模式下有效 |
| showLine | 是否显示节点间的连线(仅 mode = catalog时生效) | Boolean | false | 仅在 mode = catalog时生效 |
| lineColor | 连线颜色() | String | #ccc | 仅在 mode = catalog时生效,需与showLine配合使用 |
const toggle = (hasNode, target) => {
if (props.arrowClick && hasNode && !target && props.mode === 'catalog') return;
isExpanded.value = !isExpanded.value;
emit('toggle', { ...props.node, level: props.level, parentId: currentPID.value });
};
3.2.2 深度优先搜索(DFS) 为了在树形结构中查找特定节点,TreeNode.vue 中实现了深度优先搜索算法。该算法通过递归遍历树的每个节点,直到找到目标节点。
function depthFirstSearch(node, id) {
if (node.children && node.children.length > 0) {
if (node.children.some(item => item[props.defaultProps.id] === id)) {
currentPID.value = node[props.defaultProps.id];
}
node[props.defaultProps.children].forEach(child => depthFirstSearch(child, id));
}
}
3.2.3 样式管理 TreeComp 组件支持通过 props 自定义节点的样式,包括选中文字颜色、背景颜色、展开/收起动画等。样式的管理集中在 TreeNode.vue 的 style 部分,通过动态绑定 :style 和 :class 实现。
<div class="shawn-tree-node-label" :style="`justify-content:${mode === 'menu' ? 'space-between' : 'flex-start'};cursor:${arrowClick && mode === 'catalog' ? 'default' : 'pointer'}`">
<span class="my-label-shawn" :style="`cursor:${hasChildNode() ? 'default' : 'pointer'}`"> {{ node[defaultProps.label] }} </span>
</div>
4. 使用示例 以下是一个简单的使用示例,展示如何使用 TreeComp 组件构建一个树形菜单:
<template>
<TreeComp :treeData="treeData" mode="menu" @toggle="handleToggle" />
</template>
<script setup>
import { ref } from 'vue';
import TreeComp from './components/tree-comp/index.vue';
const treeData = ref([ { id: 1, label: '节点1', children: [ { id: 2, label: '子节点1' }, { id: 3, label: '子节点2' }, ], }, { id: 4, label: '节点2', children: [ { id: 5, label: '子节点3' }, ], }, ]);
const handleToggle = (node) => { console.log('节点被点击:', node); };
</script>
menu 模式效果
catalog 模式效果
5. 总结
TreeComp 组件通过灵活的配置和高效的事件机制,能够轻松构建和管理树形结构。无论是文件管理系统、导航菜单还是组织架构图,TreeComp 都能提供强大的支持。