ElementUI Tree 组件实战:动态添加节点与路径显示
本文详解 ElementUI Tree 组件在文件夹管理场景中的应用。通过 append 方法实现动态添加子节点,利用 node.level 属性限制仅允许创建二级目录。同时演示如何递归查找父节点,动态计算并展示当前节点的路径及父级目录名称,解决树形结构中的常见交互需求。
起因
项目近期遇到一个具体需求:后端存在一个图片存储空间,其本质是一个文件夹结构。为了在前端直观地展示这种层级关系,我们需要将这种文件夹结构以树形视图呈现出来。
具体需求如下
- 支持新建子目录,但仅限新建二级目录;当处于三级或更深层级时,新建按钮应处于禁用状态。
- 页面需展示父级目录名称及当前所在完整路径,各层级之间使用斜杠进行分隔。
- 根目录名称固定为“图片空间”。
- 页面初次加载时,调用接口仅获取一级目录数据,并默认展开展示所有一级目录。
- 当用户点击某一级目录时,根据该目录对应的 ID 请求接口以获取其下的二级目录,后续层级依此类推。
初看此需求时,我认为在 ElementUI 中已有相关实现,应该不难。但在实际开发过程中发现细节较为复杂,因此花费时间进行了深入研究,以便日后复用。
处理
首先复制 elementUI 的官方示例代码,并在此基础上添加了一些测试数据。
<template>
<div>
<el-input v-model="input"
style="width:200px"
placeholder="请输入内容"></el-input>
<el-button type="primary">添加节点</el-button>
<span>当前目录:</span>
<span>当前目录的父级目录:</span>
<el-tree :data="data"
:props="defaultProps"
accordion
@node-click="handleNodeClick"></el-tree>
</div>
</template>
<script>
export default {
data() {
return {
input: '',
data: [{
label: '图片空间',
children: [{
label: '蔬菜',
children: [{
label: '菠菜',
},
{
label: '生菜',
},
],
},
{
label: '水果',
children: [{
label: '香蕉',
}],
},
{
label: '美女',
children: [{
label: '秦岚',
}],
}],
}],
defaultProps: {
children: 'children',
label: 'label',
},
};
},
methods: {
handleNodeClick(data) {
console.log(data);
},
},
};
</script>
此时的界面效果如图所示。

需求一
我们从最简单的功能开始:在任意目录下添加子节点(子分类)。
查阅官方文档后,确定了实现方法。

该方法接收两个参数:(data, parentNode)
- 要追加的子节点数据对象
data - 子节点对应的
parent对象,其中包含data、key或node等属性
第一个参数 data 在此处仅表示节点名称。关键在于如何获取第二个参数。
要向目录添加子节点,必须先选中该目录。因此我们需要查看点击事件回调返回的数据内容。

从回调结果可以看出,第二个参数即为 节点对应的node,这正是我们需要的对象。接下来进行尝试。
修改代码如下,我们点击节点的时候,把点击事件回调的参数 node 先存在变量 nowClickNode 中,然后我们调用 append 方法的时候,再把 nowClickNode 给传过去。
// 为了节省篇幅,省略template中的代码,文末会贴出整体代码
methods: {
// 点击节点
handleNodeClick(nodes, node, self) {
this.nowClickNode = node;
},
// 添加节点
addSort() {
const data = {
label: '草莓',
};
this.$refs.tree.append(data, this.nowClickNode);
},
},功能实现成功。

如何实现仅允许新建二级目录,并在三级时禁用按钮?由于我们在点击时已保存变量 nowClickNode,该变量中包含表示层级的 level 属性。我们可以通过计算属性来实现这一限制。
//template
<el-button type="primary"
:disabled='isDisabled'
@click='addSort'>添加节点</el-button>
//js
computed: {
// 是否可以新建分类
isDisabled() {
if (this.nowClickNode.level > 2) {
return true;
}
return false;
},
},如图所示,当点击至三级目录时,按钮已变为禁用状态。

需求二
接下来实现第二个需求:显示当前所在路径及父级目录。参考上方的示例图,该功能已实现。
// 点击节点的时候触发事件
handleNodeClick(nodes, node, self) {
this.nowClickNode = node;
this.nowPathArr = [];
// 如果不是根节点
if (node.parent.parent) {
this.faterName = node.parent.data.label;
// 递归找路径
this.findParentName(node);
// 拼接路径
this.nowPath = `图片空间 / ${this.nowPathArr.join(' / ')}`;
} else {
// 如果是根节点 直接赋值
this.nowPath = '图片空间';
this.faterName = '- -';
}
},
// 查找父节点的分类名称
findParentName(node) {
if (node.parent.parent) {
this.nowPathArr.unshift(node.data.label);
this.findParentName(node.parent);
}
},
由于根节点也包含 parent 属性,我们需要额外向上查找一层,通过判断 parent.parent 是否存在来确定是否为根节点。
在点击事件中,递归查找当前节点的父元素,将所有祖先元素存入数组,最后进行字符串拼接。
需求三、四、五
剩余三个需求合并讲解。此处使用的是项目真实数据,为保护隐私已对代码进行脱敏处理。重点在于掌握实现逻辑。
//template
<el-tree
:data="treeData" //数据源
:props="defaultProps" //配置项
accordion //每次打开一个节点 手风琴模式
ref="tree" //用来获取dom
lazy //节点懒加载
:highlight-current='true' //高亮当前节点
:load='treeLoad' //懒加载时调用的方法
node-key="cateId" //唯一标识
:default-expanded-keys='defaultOpen' //默认打开的节点数组
:expand-on-click-node='true' //是否在点击节点的时候展开或者收缩节点, 默认值为 true,如果为 false,则只有点箭头图标的时候才会展开或者收缩节点。
@node-click="handleNodeClick" //点击节点的回调函数
>
</el-tree>
//js
// 加载树形结构 就是上面懒加载绑定的函数
treeLoad(node, resolve) {
// 判断节点等级
if (node.level == 0) {
// 如果是根节点,添加一个固定的图片空间节点 这是实现需求三
resolve([{
cateName: '图片空间',
cateId: '0',
children: [],
}]);
}
// 不是根节点,调取接口加载列表 这里实现需求四,五的树结构懒加载,点完一级请求一级的数据
if (node.level >= 1) {
this.getCategoryListNew(node, resolve);
// 防止子节点为空时一直出现加载动画
return resolve([]);
}
},
// 获取树形结构 上面掉用的请求接口 data处理完之后要调用resolve方法
getCategoryListNew(node, resolve) {
Service.getCategoryListNew({ parentId: node.data.cateId }).then(({ data }) => {
resolve(data);
}).catch((e) => {
console.log(e);
});
},
其他知识点
另外记录几个常用知识点。
默认展开节点
默认展开功能通过 :default-expanded-keys='defaultOpen' 属性配置,defaultOpen 数组中存放的是 node-key 的集合。
横纵向滚动条
首先需在 tree 组件外层容器设置 宽高,并配置 overflow 属性。随后需修改 el-tree 的 CSS 样式。
.tree-box{
width: 200px;
height: calc(100% - 30px);
overflow:auto;
}
.el-tree {
display: inline-block;
min-width: 100%;
}刷新某一个节点
// 通过节点id找到对应树节点对象
const node = this.$refs.tree.getNode(this.nodeId);
// 把loaded手动置为false,也就是告诉tree这个节点没有加载过
node.loaded = false;
// 主动调用展开节点方法,重新查询该节点下的所有子节点
node.expand();模拟点击一级目录中的第一个节点以触发刷新。
// 选取dom
const root = document.querySelector('.el-tree-node__children');
// 找到目标节点
const firstNode = root.firstChild;
// 模拟点击
firstNode.click();本文介绍了 ElementUI Tree 组件的基本使用实战,更多相关内容可参考本站其他文章或继续浏览后续内容,感谢支持。
JS中使用位运算(~~)和一元加号(+)快速转换字符串为整数
2026-11-03 22:41:12
怎么使用命令行批量格式化项目中的JS文件
2026-11-03 19:04:42
JS代码美化后报错怎么办?常见格式化冲突解决方法
2026-11-03 18:47:01
不用moment.js,怎么用原生JS Intl API格式化时间戳
2026-11-03 18:10:30
原生JS与dayjs获取当前日期的代码对比
2026-11-03 17:57:26
