要求:熟悉element-ui中关于table的官方例子——树形数据与懒加载
element-ui中,官方给了两种实现树形表格的方式:
1.直接加载出父项与子项所有数据并渲染
2.通过懒加载实现子项数据并渲染
本片文章主要是针对懒加载实现的方法进行深入学习,为了实现子项根据不同的操作能够动态渲染。
实现的功能有:
1.编辑子项
2.删除子项
// 补充:2020.4.3更新,之前代码有部分小问题,今日更新
// 1.针对父项中最后一个子项删除后出现报错导致查询等操作阻塞问题
Table
的代码:
<el-table
class="tree-table"
:data="List"
style="width: 100%"
row-key="keyId"
lazy
:load="handleLoad"
:tree-props="{children: 'childrenList', hasChildren: 'hasChildren'}"
v-loading="loading" max-height="530" border>
<el-table-column label="名字" prop="name" align="center"></el-table-column>
<el-table-column label="住址" prop="address" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="toEdit(scope.row)">编辑</el-button>
<el-button type="text" @click="handleDelete(scope.row)" v-if="scope.row.hasChildren !== true && scope.row.hasChildren !== false">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 编辑弹框 -->
<el-dialog class="dialog-edit" title="编辑" :visible.sync="isEdit" v-if="isEdit" width="30%">
<el-form :model="editData" ref="dateForm" :rules="dateRule">
<el-form-item label="住址:" prop="address">
<el-input placeholder="请输入" v-model="editData.address" maxlength="120" clearable></el-input>
</el-form-item>
<div class="dialog-footer">
<el-button type="primary" size="medium" @click="toSave">保存</el-button>
<el-button size="medium" @click="isEdit = false;">取消</el-button>
</div>
</el-form>
</el-dialog>
支持树类型的数据的显示。当 row
中包含 children
字段时,被视为树形数据。渲染树形数据时,必须要指定 row-key
。支持子节点数据异步加载。设置 Table 的 lazy
属性为 true 与加载函数 load
。通过指定 row
中的 hasChildren
字段来指定哪些行是包含子节点。children
与 hasChildren
都可以通过 tree-props
配置。
data
中的代码:
//Table数据格式参考:
// 注意:这边的数据格式是:有子项的,有keyId;无子项的,无keyId;
List: [
{
id: "01",
childrenList: [],
hasChildren: true,
keyId: "FE457357B8444018A8231D0AC2F8F7DD",
name: "王小虎",
address: "上海市普陀区金沙江路 1518 弄"
},
{
id: "02",
childrenList: [],
name: "卢西奥",
address: "上海市普陀区金沙江路 1517 弄"
}
],
// 记录节点
treeNode: [],
resolve: [],
// 编辑
isEdit: false,
editData: {
address: '',
keyId: '',
rowData: ''
},
methods
中的代码:
- 加载函数
load
// 加载子项时调用的方法,与 加载函数 load 绑定
handleLoad(tree, treeNode, resolve) {
let arr = [];
if (tree) {
let getData = {
id: tree.id
};
// 此处调个获取子项数据的查询接口
this.handleQuery(getData).then(res => {
if (res && res.length > 0) {
arr = [...res];
for (let i = 0; i < arr.length; i++) {
arr[i]['edit'] = false;
arr[i].name= arr[i].name; // 把子项名字换上去
// 保存此环节所有子项数量
arr[i]['numTotal'] = arr.length; // 此处为2020.4.3新增代码
// 在子项中保存父项的节点信息
// 这里需要保存 treeNode 信息和 resolve 方法,用于编辑或删除的时候能为对应子项重新渲染
arr[i]['treeNode'] = treeNode;
arr[i]['resolve'] = resolve;
}
resolve(arr); // 此处为2020.4.3新增代码
} else { // 此处为2020.4.3新增代码
// 隐藏下拉图标,暂时只能想到这种方法,由于当前饿了么库不支持设置节点的display属性
treeNode.children = [];
treeNode.level = 'null'; // 设置私有样式,覆盖饿了么自带样式,实现下拉图标隐藏
// treeNode.display = false;
treeNode.expanded = false;
treeNode.loading = false;
tree.hasChildren = false;
this.$message.warning('此环节暂无子项');
}
// resolve(arr);
}).catch(e => {
// resolve(arr);
});
}
// else {
// resolve(arr);
// }
},
此处,说明下load
函数中所带的传参是什么。
tree
:这个跟row
是一样的,得到的是你所点击加载的那条表格数据;
treeNode
:这个拿到的是当前节点的层级信息,打印如下:
{
children: Array(0),
display: true,
expanded: true,
lazy: true,
level: 0, // 此处代表父项
loaded: true,
loading: false
}
resolve
:此为element封装好的内置方法,主要用处就是 重新渲染;
2.编辑功能
// 编辑
toEdit(row) {
this.editData = {
address: row.address,
keyId: row.keyId,
rowData: row
};
this.isEdit = true;
},
// 保存
toSave() {
this.$refs.dateForm.validate(valid => {
if (valid) {
let saveData = {
id: this.editData.rowData.id,
name: this.editData.rowData.name,
keyId: this.editData.keyId? this.editData.keyId : '',
address: this.editData.address
};
// 调个保存接口
this.handleSave(saveData).then(() => {
this.$message.success('操作成功');
this.isEdit = false;
this.createdQuery();
// 以下就是能够重新渲染子项的代码
if (this.editData.rowData.treeNode.level === 0) {
this.editData.rowData.treeNode.children = [];
// 重新渲染子项
this.handleLoad(this.editData.rowData, this.editData.rowData.treeNode, this.editData.rowData.resolve);
}
}).catch(e => {});
}
});
},
3.删除功能,重新渲染子项方式与编辑一样
// 删除
handleDelete(row) {
this.$confirm('确认删除吗', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
let delData = {
keyId: row.keyId,
id: row.id
};
// 调个删除接口
this.handleDelete(delData).then(() => {
this.$message.success('操作成功');
// 判断此子项是否为最后一项 // 此处为2020.4.3新增代码
if (row.numTotal === 1) {
this.tableData = []; // 清空表格,强制让表格中的行都处于收敛状态
}
this.createdQuery(); // 此为调用查询封装的方法
// 以下就是能够重新渲染子项的代码,并且此子项不为最后一项
if (row.treeNode.level === 0 && row.numTotal !== 1) {
row.treeNode.children = [];
this.handleLoad(row, row.treeNode, row.resolve);
}
}).catch(e => {});
}).catch(() => {
this.$message.info('已取消本次操作');
});
},
此处为私人 style
<style scoped>
......
/*强制隐藏下拉图标*/
.tree-table >>> .el-table__row--level-null .el-table__expand-icon{
display: none;
}
</style>
希望本文能帮助到你,若有问题或错误欢迎留言哦~
如果有更好的方法也可以留言互相学习~
网友评论