当前位置: 首页 > news >正文

6.5 el-tree 组件

Element UI 的 el-tree 组件功能强大且易于使用。


一、 核心作用与基本结构

<el-tree> 组件用于以树形结构展示具有父子层级关系的数据。用户可以展开/折叠节点,进行选择、拖拽等操作。

最基础的示例:

<template><el-tree:data="treeData":props="defaultProps"@node-click="handleNodeClick"></el-tree>
</template><script>
export default {data() {return {// 树形数据源treeData: [{label: '一级 1',children: [{label: '二级 1-1',children: [{label: '三级 1-1-1'}]}]}, {label: '一级 2',children: [{label: '二级 2-1'}, {label: '二级 2-2'}]}],// 定义数据中关键字段的名称defaultProps: {children: 'children', // 指定子节点数组的字段名label: 'label'        // 指定节点显示文本的字段名}}},methods: {handleNodeClick(data, node, component) {console.log('点击了节点:', data);// data: 节点对应的原始数据对象// node: 节点的 Node 对象 (包含 key, level, parent 等信息)// component: 节点的 Vue 组件实例}}
}
</script>

二、 核心属性详解

<el-tree> 的行为和外观由众多属性控制。

  1. data:

    • 作用树形结构的数据源,一个包含层级关系的数组。
    • 类型Array
    • 格式: 数组中的每个对象代表一个节点。通常包含 label (显示文本) 和 children (子节点数组) 字段。具体字段名由 props 属性定义。
  2. props:

    • 作用非常关键!用于定义数据对象中哪些字段对应树节点的特定属性。
    • 类型Object
    • 可配置的键值:
      • label: 节点显示的文本对应的字段名。Function(data, node) | String
      • children: 子节点数组对应的字段名。String
      • disabled: 是否禁用节点对应的字段名。Function(data, node) | String
      • isLeaf: 是否为叶子节点对应的字段名。Function(data, node) | String (用于懒加载)
    • 示例:
      props: {label: 'name',           // 显示文本用 data.namechildren: 'subItems',    // 子节点用 data.subItemsdisabled: 'locked',      // 禁用状态用 data.locked (true/false)isLeaf: 'isFile'         // 是否叶子节点用 data.isFile (true/false)
      }
  3. node-key:

    • 作用极其重要!每个节点的唯一标识字段名。在使用 checkexpanddrag 等功能时,必须设置此属性,否则会报错或功能异常。
    • 类型String
    • 示例:node-key="'id'" (假设数据中每个节点都有唯一的 id 字段)
  4. default-expand-all:

    • 作用: 是否默认展开所有节点。
    • 类型Boolean
    • 默认值false
    • 注意: 如果数据量很大,不建议使用,会影响性能。
  5. expand-on-click-node:

    • 作用: 是否在点击节点本身(而非展开图标)时展开/折叠节点。
    • 类型Boolean
    • 默认值true
    • 示例: 设为 false 时,只有点击 +/- 图标才能展开/折叠。
  6. show-checkbox:

    • 作用: 节点是否显示复选框 (Checkbox)。
    • 类型Boolean
    • 默认值false
    • 注意: 开启后,需要配合 check-strictly 和 check-on-click-node 等属性使用。
  7. check-on-click-node:

    • 作用: 是否在点击节点时选中/取消选中节点(仅在 show-checkbox 为 true 时有效)。
    • 类型Boolean
    • 默认值false
    • 示例: 设为 true 时,点击节点文本即可勾选复选框。
  8. check-strictly:

    • 作用: 在显示复选框的情况下,是否严格的遵循父子不互相关联。
    • 类型Boolean
    • 默认值false
    • 解释:
      • false (默认): 父节点选中时,所有子节点自动选中;子节点全选中时,父节点自动选中(半选或全选)。
      • true: 父子节点选中状态完全独立,互不影响。
  9. draggable:

    • 作用: 是否开启拖拽节点功能。
    • 类型Boolean
    • 默认值false
    • 注意: 开启后需要监听 @node-drag-start@node-drag-enter@node-drag-leave@node-drag-over@node-drag-end@node-drop 事件来控制拖拽行为。
  10. allow-drag:

    • 作用: 判断节点能否被拖拽。Function(node)
    • 类型Function
    • 示例:allow-drag="node => node.data.type !== 'root'" (根节点不能拖拽)
  11. allow-drop:

    • 作用: 拖拽时判定目标节点能否被放置。Function(draggingNode, dropNode, type)type 的值为 'prev''inner''next'
    • 类型Function
    • 示例:allow-drop="allowDrop" (见下方完整示例)
  12. highlight-current:

    • 作用: 是否高亮当前选中的节点。
    • 类型Boolean
    • 默认值false
  13. default-expanded-keys:

    • 作用: 默认展开的节点的 key 数组。需要配合 node-key 使用。
    • 类型Array
    • 示例:default-expanded-keys="[2, 3]"
  14. default-checked-keys:

    • 作用: 默认勾选的节点的 key 数组。需要配合 node-key 和 show-checkbox 使用。
    • 类型Array
  15. filter-node-method:

    • 作用: 自定义节点过滤方法。配合 filter 方法使用。
    • 类型Function(value, data, node)
    • 说明: 返回 true 表示显示该节点,false 表示隐藏。

三、 核心事件详解

事件是与树形控件交互的主要方式。

  1. @node-click:

    • 触发: 点击某个节点时。
    • 参数(data, node, component) - 节点数据、节点对象、组件实例。
  2. @node-contextmenu:

    • 触发: 右键点击某个节点时。
    • 参数(event, data, node, component) - 鼠标事件、节点数据、节点对象、组件实例。常用于弹出右键菜单。
  3. @check-change:

    • 触发: 节点选中状态发生变化时(仅在 show-checkbox 为 true 时有效)。
    • 参数(data, checked, indeterminate) - 节点数据、是否被选中、是否半选。
  4. @check:

    • 触发: 当复选框被点击,或者使用 setChecked/Keys 方法时。
    • 参数(data, checkedStatus) - 节点数据、选中状态对象 { checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys }
  5. @current-change:

    • 触发: 当前选中节点变化时(需要 highlight-current 为 true)。
    • 参数(data, node) - 当前节点数据、节点对象。
  6. @node-expand / @node-collapse:

    • 触发: 节点被展开 / 折叠时。
    • 参数(data, node, component) - 节点数据、节点对象、组件实例。
  7. 拖拽相关事件 (draggable="true" 时):

    • @node-drag-start: 开始拖拽时。
    • @node-drag-enter: 拖拽进入目标节点时。
    • @node-drag-leave: 拖拽离开目标节点时。
    • @node-drag-over: 拖拽在目标节点上时。
    • @node-drag-end: 拖拽结束时。
    • @node-drop: 拖拽成功放置时。这是处理数据更新的关键事件
    • 参数: 通常包含 (draggingNode, dropNode, dropType, ev)dropType 是 'prev''inner''next'

四、 常用功能详解

1. 多选 (带复选框)
<el-tree:data="treeData":props="defaultProps"node-key="id"show-checkbox:default-checked-keys="[5]" <!-- 默认选中 id 为 5 的节点 -->@check-change="handleCheckChange"
>
</el-tree><script>
export default {methods: {handleCheckChange(data, checked, indeterminate) {console.log(`节点 ${data.label} 选中状态: ${checked}, 半选状态: ${indeterminate}`);},// 获取当前选中的节点getCheckedNodes() {return this.$refs.tree.getCheckedNodes();},// 获取当前选中节点的 keygetCheckedKeys() {return this.$refs.tree.getCheckedKeys();}}
}
</script>
2. 懒加载 (Lazy Load)

适用于数据量巨大或需要按需加载的场景(如文件系统)。

<el-tree:data="treeData":props="props"node-key="id":load="loadNode"lazy@node-click="handleNodeClick"
>
</el-tree><script>
export default {data() {return {props: {label: 'name',children: 'zones',isLeaf: 'leaf' // 标记是否为叶子节点}}},methods: {loadNode(node, resolve) {// node: 当前节点的 Node 对象// resolve: 回调函数,用于返回子节点数据if (node.level === 0) {// 根节点return resolve([{ name: 'Root1', leaf: false }, { name: 'Root2', leaf: true }]);}if (node.level > 3) return resolve([]); // 最多展示到 4 级// 模拟异步加载setTimeout(() => {const data = [{name: 'Child1',leaf: node.level >= 3 // 4级以后是叶子节点}, {name: 'Child2',leaf: node.level >= 3}];resolve(data);}, 500);}}
}
</script>
3. 自定义节点内容 (使用插槽)

这是实现复杂节点(如带图标、按钮)的关键。

<el-tree:data="treeData":props="defaultProps"node-key="id"default-expand-all@node-click="handleNodeClick"
><!-- 使用 scoped slot 自定义节点内容 --><span class="custom-tree-node" slot-scope="{ node, data }"><span>{{ node.label }}</span><span><el-buttontype="text"size="mini"@click="() => append(data)">Append</el-button><el-buttontype="text"size="mini"@click="() => remove(node, data)">Delete</el-button></span></span>
</el-tree><style>
.custom-tree-node {flex: 1;display: flex;align-items: center;justify-content: space-between;font-size: 14px;padding-right: 8px;
}
</style><script>
export default {methods: {append(data) {const newChild = { id: id++, label: 'testtest', children: [] };if (!data.children) {this.$set(data, 'children', []);}data.children.push(newChild);},remove(node, data) {const parent = node.parent;const children = parent.data.children || parent.data;const index = children.findIndex(d => d.id === data.id);children.splice(index, 1);}}
}
</script>
4. 拖拽 (Drag & Drop)
<el-tree:data="treeData":props="defaultProps"node-key="id"draggable:allow-drop="allowDrop":allow-drag="allowDrag"@node-drop="handleDrop"
>
</el-tree><script>
export default {methods: {// 判断节点是否可以被拖拽allowDrag(node) {// 例如:根节点不能拖拽return node.data.id !== 1;},// 判断拖拽时目标节点是否可以被放置allowDrop(draggingNode, dropNode, type) {// 例如:禁止将节点拖拽到根节点下if (dropNode.data.id === 1 && type === 'inner') {return false;}// 例如:禁止将父节点拖拽到其子节点下if (type === 'inner' || type === 'prev') {let parent = dropNode.parent;while (parent && parent !== this.$refs.tree.root) {if (parent.data.id === draggingNode.data.id) {return false;}parent = parent.parent;}}return true;},// 处理拖拽放置后的逻辑handleDrop(draggingNode, dropNode, dropType, ev) {console.log('Drop:', draggingNode, dropNode, dropType);// 在这里更新你的数据源 treeData// 通常需要根据 dropType ('prev', 'inner', 'next') 将 draggingNode.data 插入到 dropNode.data 的相应位置this.$message.success('节点已移动');}}
}
</script>
5. 节点过滤 (Filter)
<el-inputplaceholder="输入关键字进行过滤"v-model="filterText">
</el-input><el-treeclass="filter-tree":data="treeData":props="defaultProps"node-key="id":filter-node-method="filterNode"ref="tree"
>
</el-tree><script>
export default {watch: {// 监听 filterText 的变化filterText(val) {// 调用树的 filter 方法this.$refs.tree.filter(val);}},methods: {// 自定义过滤逻辑filterNode(value, data) {if (!value) return true; // 空值时显示所有// 过滤 label 字段return data.label.indexOf(value) !== -1;// 也可以过滤其他字段// return data.label.indexOf(value) !== -1 || data.description.indexOf(value) !== -1;}}
}
</script>

五、 高级技巧与最佳实践

  1. node-key 必须设置: 这是几乎所有高级功能(多选、展开、拖拽)正常工作的前提。
  2. 性能考虑:
    • 避免一次性加载过深或过宽的树。
    • 大数据量时优先使用懒加载 (lazy)。
    • 避免使用 default-expand-all
  3. 数据更新: 直接修改 data 数组可能不会触发视图更新。推荐使用 Vue 的响应式方法:
    • this.$set(data, 'children', newChildrenArray)
    • this.$delete(childrenArray, index)
    • 或者直接替换整个 treeData 数组。
  4. 方法调用<el-tree> 提供了丰富的实例方法,如 getCheckedNodes()setCheckedKeys()updateKeyChildren()getNode()remove()append()filter() 等,通过 ref 调用。
  5. 样式定制: 可以通过 CSS 覆盖 .el-tree-node.el-tree-node__content.el-tree-node__label 等类名来定制样式。

总结

Element UI 的 <el-tree> 组件是一个功能非常全面的树形控件。掌握其核心属性 data, props, node-keyshow-checkbox,以及关键事件 @node-click@check-change 是基础。灵活运用 scoped slot 可以实现高度自定义的节点内容。对于复杂场景,懒加载 (lazy) 是处理大数据量的利器,拖拽 (draggable) 和 过滤 (filter) 功能则极大地提升了交互性。node-key 是几乎所有高级功能的基石,务必正确设置。

http://www.dtcms.com/a/351766.html

相关文章:

  • 用大语言模型实现语音到语音翻译的新方法:Scheduled Interleaved Speech-Text Training
  • Research相关的面试(个人)
  • 云服务器的作用
  • yggjs_rbutton React按钮组件v1.0.0 API 参考文档
  • linux、window java程序导出pdf\word、excel文字字体显示异常、字体样式不一样
  • 【lucene】spancontainingquery
  • 8月26日
  • 【QT学习之路】-Qt入门
  • 新型隐蔽恶意软件利用TP-Link、思科等路由器漏洞获取远程控制权
  • ZMC900E如何实现多主站协同控制?
  • 【typenum】 29 类型级别的数字数组标记特质(TypeArray)
  • 基于政策传导因子与就业脆弱性指数的鲍威尔9月降息决策分析
  • Prometheus 告警组件 Alertmanager 的使用并接入 Grafana
  • docker 安装nacos(vL2.5.0)
  • Android之讯飞语音合成和语音识别
  • React 代码规范
  • 算法练习-合并两个有序数组
  • 表格比对的实现
  • 如何确定哪些层应添加适配器(Adapter)?(58)
  • 餐中服务:藏在菜香里的 “情感传递术”
  • Java继承与虚方法详解
  • 掌握常用CSS样式:从基础到实战的全面指南
  • 从0开始学习Java+AI知识点总结-26.web实战(Springboot原理)
  • 产品经理成长手册(2)——产品文档能力
  • 14、RocketMQ生产环境如何优化
  • Linux查看服务器内存、磁盘、cpu、网络占用、端口占用情况
  • THM El Bandito
  • 设计模式学习笔记-----抽象责任链模式
  • 常见的设计模式
  • 深度学习篇---1*1卷积核的升维/降维