问题形容
我的项目中应用树结构,次要信息个别在树的叶子节点上记录。然而有些状况下,后端是不把一些树叶子节点的状态信息做记录的,比方树叶子节点的状态(是否增加、是否珍藏什么的),后端只是把树结构所须要的数据返回给前端,至于状态什么的,前端须要去记录,而且状态的更改,也是须要前端去记录更改的
咱们先看一下我的项目的效果图:
效果图
功能分析
- 当咱们点击左侧的叶子节点的时候,更改叶子节点成已增加的状态,同时将左侧的数据追加到右侧的表格中去:即:
(点击叶子节点,更改叶子节点状态)
- 当咱们再次点击叶子节点的时候,将叶子节点已增加的状态,批改成未增加的状态,同时删除右侧表格中的对应项:即:
(点击叶子节点,更改叶子节点状态)
- 当咱们删除右侧表格中的某一项时候,同时更改左侧的叶子节点的状态:即:
(递归更改左侧树结构对应节点的状态)
本例是树组件懒加载的写法,对于树组件懒加载的写法,也能够参考我之前的一篇文章,传送门:https://segmentfault.com/a/11…
点击叶子节点,更改叶子节点状态
// 点击树组件节点上的增加或未增加按钮,更改树的增加未增加的状态,同时追加或删除右侧表格中对应的行的数据
changeStatus(node, data) {// console.log("data 是点击的这个树节点所绑定的数据", data);
if (data.status == "0") {
data.status = "1"; // 这里咱们能够间接更改树节点上的对应数据,便会失效,未增加变成已增加
this.tableData.push(data); // 追加进右侧表格
} else if (data.status == "1") {
data.status = "0"; // 已增加变成未增加
this.tableData.forEach((item, index) => {
// 同时,依据 id 去删除掉右侧的数据
if (item.id == data.id) {this.tableData.splice(index, 1);
}
});
}
}
留神 html 中的这个 changeStatus 办法是点击按钮的高阶函数的写法,这样:
@click="() => changeStatus(node, data)"
递归更改左侧树结构对应节点的状态
// 第一步:依据删除或者 id,而后依据 id 递归更改树节点状态字段
// 第二步:把表格中的数据删除即可
removeRow(row) {// console.log("行数据", row.id);
// 获取 tree 的所有的 node 节点数组(DOM 节点),这里是两个数组,对应的就是西游记和三国演义的最外层的数组()let allNodesDom = this.$refs.myTree.root.childNodes;
console.log("node 节点树结构", allNodesDom);
function bianli(checkedData) {for (const i in checkedData) {
// 阐明到最内层了
if (checkedData[i].childNodes.length == 0) {
// 到最内层当前,就看看对应的 id,是否与移除行的 id 统一
if (checkedData[i].data.id == row.id) {
// 若 id 统一,就更改树组件的最内层节点的数据即可
checkedData[i].data.status = "0";
break;
}
} else if (checkedData[i].childNodes.length > 0) {
// 阐明没到最内层,那就持续递归调用本人,持续找
bianli(checkedData[i].childNodes);
}
}
return;
}
bianli(allNodesDom); // 递归调用,更改数据
// 同时依据 id 删除右侧的表格对应的行
this.tableData.forEach((item, index) => {if (item.id == row.id) {this.tableData.splice(index, 1);
}
})
}
代码附上
<template>
<div class="box">
<!-- 左侧树局部 -->
<div class="leftBox">
<el-tree ref="myTree" :props="props" :load="loadNode" lazy node-key="id">
<span slot-scope="{node, data}">
<i
class="el-icon-folder-opened"
style="color: #448ff7"
v-show="node.isLeaf !== true"
></i>
<!-- <span style="padding-left: 8px">{{node.label}}</span> -->
<span style="padding-left: 8px">{{data.name}}</span>
<el-button
style="margin-left: 12px"
size="small"
type="text"
v-show="node.isLeaf === true"
@click="() => changeStatus(node, data)"
>
<span :class="{highLightTree: data.status =='0'}">{{data.status == "0" ? "未增加" : "已增加"}}</span>
</el-button>
</span>
</el-tree>
</div>
<!-- 右侧表格局部 -->
<div class="rightBox">
<el-table
:data="tableData"
border
style="width: 100%"
:header-cell-style="{
height: '48px',
background: '#FAFAFA',
color: '#333333',
fontWeight: 'bold',
}"
>
<el-table-column prop="id" label="id 编号"></el-table-column>
<el-table-column prop="name" label="姓名"></el-table-column>
<el-table-column prop="home" label="地址"></el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button
@click="removeRow(scope.row)"
type="danger"
plain
size="small"
> 移除 </el-button
>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script>
export default {data() {
return {
props: {
label: "name",
isLeaf: "isLeaf",
},
tableData: [],};
},
methods: {
// 初始加载最外层节点
loadNode(node, resolve) {
// 点击节点加载相应节点的数据
if (node.level == 0) {this.loadfirstnode(resolve);
}
// 如果开展其余级节点,动静从后盾加载下一级节点列表
if (node.level >= 1) {this.loadchildnode(node, resolve);
}
},
// 加载第一级节点
async loadfirstnode(resolve) {
let params = {level: 0,};
const res = await this.$api.getTreeData(params);
return resolve(res.data);
},
// 加载节点的子节点汇合
async loadchildnode(node, resolve) {// console.log("超过二级的", node, node.level);
let params = {id: node.key,};
const res = await this.$api.getTreeChildData(params);
return resolve(res.data);
},
// 点击树组件节点上的增加或未增加按钮,更改树的增加未增加的状态,同时追加或删除右侧表格中对应的行的数据
changeStatus(node, data) {// console.log("data 是点击的这个树节点所绑定的数据", data);
if (data.status == "0") {
data.status = "1"; // 这里咱们能够间接更改树节点上的对应数据,便会失效,未增加变成已增加
this.tableData.push(data); // 追加进右侧表格
} else if (data.status == "1") {
data.status = "0"; // 已增加变成未增加
this.tableData.forEach((item, index) => {
// 同时,依据 id 去删除掉右侧的数据
if (item.id == data.id) {this.tableData.splice(index, 1);
}
});
}
},
// 第一步:依据删除或者 id,而后依据 id 递归更改树节点状态字段
// 第二步:把表格中的数据删除即可
removeRow(row) {// console.log("行数据", row.id);
// 获取 tree 的所有的 node 节点数组(DOM 节点),这里是两个数组,对应的就是西游记和三国演义的最外层的数组()let allNodesDom = this.$refs.myTree.root.childNodes;
console.log("node 节点树结构", allNodesDom);
function bianli(checkedData) {for (const i in checkedData) {
// 阐明到最内层了
if (checkedData[i].childNodes.length == 0) {
// 到最内层当前,就看看对应的 id,是否与移除行的 id 统一
if (checkedData[i].data.id == row.id) {
// 若 id 统一,就更改树组件的最内层节点的数据即可
checkedData[i].data.status = "0";
break;
}
} else if (checkedData[i].childNodes.length > 0) {
// 阐明没到最内层,那就持续递归调用本人,持续找
bianli(checkedData[i].childNodes);
}
}
return;
}
bianli(allNodesDom); // 递归调用,更改数据
// 同时依据 id 删除右侧的表格对应的行
this.tableData.forEach((item, index) => {if (item.id == row.id) {this.tableData.splice(index, 1);
}
})
}
},
};
</script>
对于本篇文章的前后端的残缺代码,欢送到我的 Gitee 上下载哈,后端用 express 模仿数据接口返回前端,传送门如下 https://gitee.com/ah-shuai/de…