我这里做的是默认选择树结构的最后一项,需求是高亮默认选中的数据。
整个树结构的代码我先都放上来然后逐一来说
<template>
<div class="box">
<div v-loading="isLoading" class="comp-tree">
<el-button
class="comp-tr-top"
type="primary"
size="small"
@click="handleAddTop"
>新增分组</el-button
>
<!-- tree -->
<el-tree
ref="SlotTree"
:data="setTree"
highlight-current
:props="defaultProps"
:expand-on-click-node="false"
:node-key="NODE_KEY"
@node-click="handleBucketClick"
:current-node-key="current_node_key"
>
<div class="comp-tr-node" slot-scope="{ node, data }">
<!-- 编辑状态 -->
<template v-if="node.isEdit">
<el-input
v-model="data.name"
autofocus
size="mini"
:ref="'slotTreeInput' + data[NODE_KEY]"
@blur.stop="handleInput(node, data)"
@keyup.enter.native="handleInput(node, data)"
></el-input>
</template>
<!-- 非编辑状态 -->
<template v-else>
<!-- 名称: 新增节点增加class(is-new) -->
<span
:class="[
data[NODE_KEY] < NODE_ID_START ? 'is-new' : '',
'comp-tr-node--name',
]"
>
{{ node.label }}
</span>
<!-- 按钮 -->
<span class="comp-tr-node--btns">
<!-- 编辑 -->
<span
icon="el-icon-edit"
size="mini"
circle
type="info"
@click="handleEdit(node, data)"
v-show="showEdit"
>
<i class="iconfont icon-bianji"></i>
</span>
<!-- 删除 -->
<span
icon="el-icon-delete"
size="mini"
circle
type="danger"
@click="handleDelete(node, data)"
v-show="showDel"
>
<i class="iconfont icon-shanchu"></i>
</span>
</span>
</template>
</div>
</el-tree>
</div>
<div>
<station-info :data="nodeClick" />
</div>
</div>
</template>
<script>
import { GroupTree, GroupInfo, DelGroupInfo } from "@/api/taos.js";
import stationInfo from "./stationInfo.vue";
import { mapState } from "vuex";
export default {
components: { stationInfo },
name: "station",
data() {
return {
current_node_key: "", //默认选中id
showEdit: true,
showDel: true,
nodeClick: "", //选中节点id
nodeId: "", //树节点id
leafId: "", //叶节点id
isLoading: false, // 是否加载
setTree: [], // tree数据
NODE_KEY: "id", // id对应字段
MAX_LEVEL: 3, // 设定最大层级
NODE_ID_START: 0, // 新增节点id,逐次递减
startId: null,
defaultProps: {
// 默认设置
children: "childList", //这里要和后端给的值对应上
label: "name",
},
//新增一级
initParam: {
// 新增参数
name: "分组",
pid: 0,
childList: [
{ name: "遥测" },
{ name: "遥信" },
{ name: "遥控" },
{ name: "遥调" },
],
},
};
},
created() {
// 初始值
this.startId = this.NODE_ID_START;
this.getGroupTree();
},
watch: {
nodeClick(val) {},
current_node_key: { //踩坑1:在这里监听current_node_key,之前写在mounted里,我发现是获取不到选中的id的
handler(value){
console.log("value",value);
if(value){
this.$nextTick(() => { //踩坑2:this.$nextTick要写,this.$nextTick 将回调延迟到下次DOM更新循环之后执行,在修改数据之后立即使用它,然后等待DOM更新,否则监听不到current_node_key。
this.$refs.SlotTree.setCurrentKey(this.current_node_key);
});
}
},
immediate:true,
},
},
mounted() {
// this.$nextTick(()=>{
// this.$refs.SlotTree.setCurrentKey(this.current_node_key)
// })
},
methods: {
//获取当前选中树结构id
handleBucketClick(val) {
console.log("树结构", val);
this.nodeClick = val.id;
//保存选中type
this.$store.commit("getType", val.type);
//保存选中groupId
this.$store.commit("getGroupId", val.id);
},
//树结构
async getGroupTree() {
const { data } = await GroupTree();
console.log("树结构详情", data.data);
if (data.code === 200) {
this.setTree = data.data;
this.setTree.forEach((e) => {
//最后一个节点作为选中的节点(缓存vuex,展示列表)
this.current_node_key = e.id;
e.childList.forEach((i) => {
if (i.type === "AI" || "AO" || "DI" || "DO") {
this.showEdit = true;
} else {
this.showEdit = true;
}
});
});
// 缓存默认groupId
this.$store.commit("getCurrent_node_key", this.current_node_key);
}
},
handleDelete(_node, _data) {
// 删除节点
// 删除操作
let DeletOprate = () => {
this.$nextTick(() => {
if (this.$refs.SlotTree) {
this.nodeId = this.$store.state.taosStore.groupId;
console.log("删除id", this.nodeId);
const { data } = DelGroupInfo(this.nodeId);
this.$message.success("删除成功!");
//TODO删除
// if (data.code === 200) {
// this.$message({
// message: "删除成功",
// type: "success",
// });
// }
this.$refs.SlotTree.remove(_data);
}
});
};
// 二次确认
let ConfirmFun = () => {
this.$confirm("是否删除此节点?", "提示", {
confirmButtonText: "确认",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
DeletOprate();
})
.catch(() => {});
};
// 判断是否新增: 新增节点直接删除,已存在的节点要二次确认
_data[this.NODE_KEY] < this.NODE_ID_START ? DeletOprate() : ConfirmFun();
this.getGroupTree();
},
async handleInput(_node, _data) {
// 修改节点
// 退出编辑状态
if (_node.isEdit) {
this.$set(_node, "isEdit", false);
const { data } = GroupInfo(_data);
}
},
// 点击编辑图标
handleEdit(_node, _data) {
// 编辑节点
// 设置编辑状态
if (!_node.isEdit) {
this.$set(_node, "isEdit", true);
}
// 输入框聚焦
this.$nextTick(() => {
if (this.$refs["slotTreeInput" + _data[this.NODE_KEY]]) {
this.$refs[
"slotTreeInput" + _data[this.NODE_KEY]
].$refs.input.focus();
}
});
},
async handleAddTop() {
// 添加顶部节点
let obj = JSON.parse(JSON.stringify(this.initParam)); // copy参数
// obj[this.NODE_KEY] = --this.startId; // 节点id:逐次递减id
this.setTree.unshift(obj);
const { data } = GroupInfo(obj);
},
},
};
</script>
<style lang="less" scoped>
// 树结构默认选中样式
/deep/.el-tree--highlight-current
.el-tree-node.is-current
> .el-tree-node__content {
color: #4d95fd;
}
.box {
display: flex;
flex-direction: row;
// width: 100%;
}
// /* common end */
.comp-tree {
padding: 20px;
height: calc(100% - 40px);
background-color: #fff;
border-radius: 8px;
width: 200px !important;
// max-width: 700px;
height: 85.8vh;
// overflow: auto;
// 顶部按钮
.comp-tr-top {
width: 100px;
margin-bottom: 2em;
font-size: 16px;
}
// 自定义节点
.el-tree {
width: 200px;
}
/deep/.comp-tr-node {
padding: 10px 0 15px 0;
display: block !important;
width: 100% !important;
position: relative !important;
// 固有label
.comp-tr-node--name {
display: inline-block;
font-size: 16px;
line-height: 40px;
min-height: 40px;
// 新增label
&.is-new {
font-weight: 500;
font-size: 16px;
}
}
}
/deep/.comp-tr-node--btns {
margin-left: 10px;
// opacity: 0;
position: absolute !important;
right: 0 !important;
top: 20px !important;
}
// 高亮显示按钮
.is-current {
& > .el-tree-node__content {
.comp-tr-node--btns {
opacity: 1;
}
}
}
// 悬浮显示按钮
.el-tree-node__content {
&:hover {
.comp-tr-node--btns {
opacity: 1;
}
}
}
}
</style>
总的来说设置默认选中状态就是要current_node_key和setCurrentKey配合使用,然后还要注意的是要加this.$nextTick,不然获取不到id,代码中我也注释说明了,还有就是很多博客说highlight-current的位置要稍微置后写,不然高亮给不到,但是我实验了不管前后顺序都是ok的。