官网:Element - The world's most popular Vue UI framework
应用场景:
1、自定义树节点内容,鼠标悬浮树节点,右侧出现节点增删改操作;
2、树形控件增加纵向滚动条;
3、关键字过滤树节点数据;
4、节点文本数据自适应宽度且溢出省略;
5、默认展开第一个节点;
代码如下:
<el-scrollbar class="treeWrap">
<div class="treeSearch">
<el-input placeholder='请输入关键词' v-model="keywords"></el-input>
</div>
<el-tree
class="el-tree"
ref="treeRef"
:data="treeData"
node-key="id"
:props="defaultProps"
:highlight-current="true"
:expand-on-click-node="false"
:default-expanded-keys="defaultExpandedIdArr",
:filter-node-method="filterNode"
@node-click="nodeClick"
>
<div
class="custom-tree-node"
slot-scope="{ node, data }",
@mouseenter="labelHover($event, node, data)"
@mouseleave="labelHoverLeave($event, node, data)"
>
<el-tooltip
effect="dark",
:content="node.label",
placement="top-start",
:open-delay="1000"
>
<span class="labelName">{{ node.label}}</span>
</el-tooltip>
<span class="showIcon" v-show="node.showIcon">
<i class="iconfont icon-xinjianwenjianjia"
@click.stop="iconClick(data, node, 1)">
</i>
<i class="iconfont icon-bianji"
@click.stop="iconClick(data, node, 2)">
</i>
<i class="iconfont icon-lajitong"
@click.stop="iconClick(data, node, 3)">
</i>
<i class="iconfont icon-icon-shuju3"
@click.stop="iconClick(data, node, 4)">
</i>
</span>
</div>
</el-tree>
</el-scrollbar>
el-scrollbar:el-scrollbar滚动条组件在官网文章中没有介绍源码中是有的,要注意的是el-scrollbar需要指定高度,该元素的内容就是滚动条要包裹的内容;
el-tree的属性和事件官网都有注释,在这里主要解释一下几点:
node-key:树节点用来作为唯一标识的属性,正常情况下设置数据的id;
filter-node-method:对树节点筛选执行的方法;
node-click:节点被点击时的回调事件;
slot-scope="{ node, data }":自定义树节点内容;
default-expanded-keys:默认展开的节点的key数组;
setCurrentKey:el-tree控件自身方法,参数(key) 为被选节点的 key,若为 null 则取消当前高亮的节点,通过 key 设置某个节点的当前选中状态,使用此方法必须设置 node-key 属性
data定义的数据:
data() {
return {
currentNode: null,//当前节点数据
treeData: [],//树节点数据
defaultProps: {//配置选项
children: "children",//子树为节点对象的children属性值
label: "name",//节点标签为节点对象的name属性值
},
}
},
关键字过滤树节点数据事件: watch监控关键字变化执行过滤事件,返回的数据为符合条件的节点树结构;
watch: {
keywords(val) {
this.$refs.treeRef.filter(val);
},
},
filterNode(value, data, node) {
if (!value) return true;
// return node.label.indexOf(value) !== -1;
//此处过滤只返回符合条件的节点,之后代码返回符合条件的节点树结构,根据需求自行选择
let arr = [];
this.getReturnNode(node,arr,value)
let result = false
arr.forEach(v=>{
result = result || v
})
return result
},
getReturnNode(node,arr,value){
let pass = node.data&&node.label.indexOf(value) !== -1
pass? arr.push(pass) : ''
if(!pass && node.level != 1 && node.parent){
this.getReturnNode(node.parent,arr,value)
}
},
鼠标移入移出显示操作项事件:
labelHoverLeave(event, node, data) {
this.$set(node, "showIcon",false );
},
labelHover(event, node, data) {
this.$set(node, "showIcon", true);
},
树节点点击事件:回调参数有event,该节点对应对象数据,节点对应的Node,节点组件本身数据
nodeClick(data, node, item) {
//根据需求自行写入
}
节点操作项事件:
iconClick(data, node, index) {
this.currentNode = node
if (index == 1) { // 添加子数据
this.$prompt('请输入节点名称', '添加子节点', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputValue: '',
inputPattern: /.{3}$/,
inputErrorMessage: '请输入节点名称,不少于3个字'
}).then(({ value }) => {
//调取接口执行添加事件
this.$message.success('添加成功!')
this.getTreeData()//添加成功之后更新树控件数据
}).catch(() => {});
} else if (index == 2) { // 编辑
this.$prompt('请输入节点名称', '编辑子节点', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputValue: node.label,
inputPattern: /.{3}$/,
inputErrorMessage: '请输入节点名称,不少于3个字'
}).then(({ value }) => {
//调取接口执行编辑事件
this.$message.success('编辑成功!')
this.getTreeData()//编辑成功之后更新树控件数据
}).catch(() => {});
} else if (index == 3) { // 删除
if (node.childNodes.length > 0) {
this.$message.warning("存在下级子设施,无法删除!");
return false;
}
this.$confirm('确认删除该节点?', '提示信息').then(() => {
//调取接口执行删除事件
this.$message.success('删除成功!')
this.currentNode = null
this.getTreeData()//删除成功之后更新树控件数据
}).catch(()=>{})
}else{}
},
默认展开第一个节点数据:default-expanded-keys和setCurrentKey都可以实现该效果,且刷新数据后需要保留之前展开状态
async getTreeData () {
const { result } = await this.$api[xxx]()//调取接口树控件数据
if (!result) {
this.$message.error('数据错误,请联系管理员!')
return
}
this.treeData = result || []
let id = this.currentNode?.data?.id?
this.currentNode.data.id: this.treeData.length>0?
this.findTree(this.treeData).id : -1;
//编辑新增刷新数据保留之前节点展开状态
this.$nextTick(() => {
this.$refs.treeRef.setCurrentKey(id)
//通过 keys 设置目前勾选的节点,使用此方法必须设置 node-key 属性,
//也可以根据default-expanded-keys设置
});
},
findTree(array) {//递归返回第一个树节点的数据
if (!array[0].children||array[0]?.children?.length==0) {
return {
id:array[0].id,
name:array[0].name,
}
} else {
return this.findTree(array[0].children);
}
},
css样式设置:
.treeWrap{
height: 100%;
width: 260px;
::v-deep(.el-scrollbar__bar.is-horizontal){
display: none;
}
::v-deep .el-scrollbar__wrap {
overflow-x: hidden !important;
}
.treeSearch{
width:250px;
padding:10px 0px 10px 8px;
position:fixed;
background:#fff;
z-index:2000
}
.el-tree{
padding-top: 60px;
.custom-tree-node{
flex: 1;
min-width: 0;
display: flex;
height: 32px;
align-items: center;
justify-content: space-between;
padding-right: 8px;
height: 100%;
box-sizing: border-box;
.showIcon {
right: 10px;
padding-right: 2px;
z-index: 1000;
background-color: #f0f7ff;
}
.labelName{
flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding: 2px 0px !important;
box-sizing: border-box;
}
}
}
}