高效构建树形结构的 Vue 组件

694 阅读3分钟

在现代前端开发中,树形结构(Tree)是一种常见的数据展示方式,广泛应用于目录、菜单、文件系统等场景。本文将介绍一个高效的 Vue 组件 TreeComp,它能够轻松构建和管理树形结构,支持多种模式和自定义配置。

1. 组件简介 TreeComp 是一个基于 Vue 3 的树形结构组件,具有以下特点:

  • 支持多种模式:包括目录模式(catalog)和菜单模式(menu),满足不同场景的需求。
  • 灵活的配置:支持自定义节点样式、展开/收起动画、选中状态等。
  • 事件驱动:通过事件机制实现节点展开/收起、选中等操作的回调。
  • 高性能:采用递归组件和深度优先搜索(DFS)算法,确保在大数据量下的性能表现。

2. 使用场景 TreeComp 组件适用于以下场景:

  • 文件管理系统:展示文件夹和文件的层级结构。
  • 导航菜单:构建多级菜单,支持展开和收起。
  • 组织架构图:展示公司或团队的层级关系。
  • 分类目录:如电商网站的商品分类、博客的标签分类等。

3. 核心代码解析

3.1 组件结构 TreeComp 组件由三个主要部分组成:

  1. Tree.vue:根组件,负责渲染整个树形结构。
  2. TreeNode.vue:节点组件,负责渲染单个节点及其子节点。
  3. index.vue:入口组件,负责接收外部数据并传递给 Tree.vue

3.2 核心功能实现

3.2.1 节点展开/收起 在 TreeNode.vue 中,通过 toggle 方法实现节点的展开和收起。该方法会根据当前节点的状态(是否展开)以及是否有子节点来更新 isExpanded 的值,并通过 emit 事件通知父组件。

4.属性配置

属性名描述类型默认值备注
animate动画模式Enumexpandcollapse -- 伸缩过渡动画, expand -- 渐变过渡动画
mode工作模式Enumcatalogcatalog -- 目录模式, menu -- 菜单模式
activeBgColor选中节点背景颜色String#F7F8FC仅 mode = menu时生效
stepValue层级左间距(仅 mode = catalog时生效)Number15仅在目录模式下有效
defaultProps键值对属性匹配Object{id:"id",children:"children",label:"label"}定义数据对象中的键与组件属性的对应关系
arrowClick是否点击箭头才展开/收起节点(仅 mode = catalog时生效)Booleanfalse仅在目录模式下有效
showLine是否显示节点间的连线(仅 mode = catalog时生效)Booleanfalse仅在 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.vuestyle 部分,通过动态绑定 :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 模式效果

image.png

catalog 模式效果

image.png

5. 总结

TreeComp 组件通过灵活的配置和高效的事件机制,能够轻松构建和管理树形结构。无论是文件管理系统、导航菜单还是组织架构图,TreeComp 都能提供强大的支持。