该篇的模拟的功能:ElementUI 树形表格懒加载数据展示,并对某列数据进行相应操作(新增,修改和删除),并对列表进行局部的数据刷新。
模拟效果图如下:
1. 注意到到点的就是,后端返回的数据结构类型中,每一层级都得包含父级的标识,如下的 parentId 的父级的 id为 0,自己的 id 为1:
{
id: 1,
parentId: 0,
date: '2016-05-02',
name: '王小虎1',
address: '上海市普陀区金沙江路 1518 弄'
},
2. 使用到的主要方法是懒加载的方法:
async loadSearch(row, treeNode, resolve) {
this.maps.set(row.id, { row, treeNode, resolve })
const loadData = [
{
id: 3100,
parentId: 32,
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
},
{
id: 3200,
parentId: 32,
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}
]
await setTimeout(() => {
resolve(loadData)
}, 2000)
await this.setNewRowData(row, loadData)
},
3.这里还用到了 Map 对象的知识,主要用于存储懒加载级的 key 以及对应的 value,这样方便触发上述懒加载方法时,取到对应的 { row, treeNode, resolve } 值,再进行懒加载,存储方法:
this.maps.set(row.id, { row, treeNode, resolve })
4. 局部刷新 封装了一个公共方法:
先从上述的 map 对象取到这个 parentId 对应的 { row, treeNode, resolve } ,之后将 该 parentId 之前懒加载的数据置空,然后再去请求懒加载方法获取新的子集数据。
// 重新触发树形表格的loadSearch函数
refreshLoadTree(parentId) {
// 根据父级id取出对应节点数据
const { row, treeNode, resolve } = this.maps.get(parentId)
this.$set(
this.$refs.multipleTable.store.states.lazyTreeNodeMap,
parentId,
[]
)
if (row) {
this.loadSearch(row, treeNode, resolve)
}
},
5. 注意注意,可能踩坑点:在删除后局部刷新的时候,若是在开发中使用到的多个标识被用到,比如 上述 id 、modivcode 和 parentId等等,但是使用到的就只有modivcode 和 parentId两个字段进行对应的操作,但是 上述的 table 绑定的却是 row-key="id", 你最后会发现在删除某个最后的叶子节点时候,发现删除成功了,但是页面没刷新。但是多个叶子节点删除没这问题,那是由于懒加载的数据标识变成了上述的 id了,导致找不到这个点。这个时候 上述的 row-key 需要绑定为modivcode 就可正常, 即 row-key="modivcode"。注意 modivcode 是唯一的.
6. 完整的代码如下:
包含的功能:多选、局部加载刷新功能。
<template>
<div>
<el-table
:data="tableData"
style="width: 100%;margin-bottom: 20px;"
row-key="id"
border
default-expand-all
lazy
:load="loadSearch"
:select-on-indeterminate="true"
@select="select"
@select-all="selectAll"
@selection-change="selectionChange"
ref="multipleTable"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
>
<el-table-column type="selection" width="55"> </el-table-column>
<el-table-column prop="date" label="日期" sortable width="180">
</el-table-column>
<el-table-column prop="name" label="姓名" sortable width="180">
</el-table-column>
<el-table-column prop="address" label="地址"> </el-table-column>
<el-table-column fixed="right" label="操作" width="100">
<template slot-scope="scope">
<el-button @click="handleAdd(scope.row)" type="text" size="small"
>新增</el-button
>
<el-button @click="handleClick(scope.row)" type="text" size="small"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
data() {
return {
maps: new Map(),
tableData: [
{
id: 1,
parentId: 0,
date: '2016-05-02',
name: '王小虎1',
address: '上海市普陀区金沙江路 1518 弄'
},
{
id: 2,
parentId: 0,
date: '2016-05-04',
name: '王小虎2',
address: '上海市普陀区金沙江路 1517 弄'
},
{
id: 3,
parentId: 0,
date: '2016-05-01',
name: '王小虎3',
address: '上海市普陀区金沙江路 1519 弄',
children: [
{
id: 31,
parentId: 3,
date: '2016-05-01',
name: '王小虎31',
address: '上海市普陀区金沙江路 1519 弄',
children: [
{
id: 311,
date: '2016',
name: '测试',
address: '上海市普陀区金沙江路 1519 弄'
},
{
id: 312,
date: '2016-01',
name: '测试2',
address: '上海市普陀区金沙江路 1519 弄'
}
]
},
{
id: 32,
parentId: 3,
date: '2016-05-01',
name: '王小虎4',
address: '上海市普陀区金沙江路 1519 弄',
hasChildren: true
}
]
},
{
id: 4,
parentId: 0,
date: '2016-05-03',
name: '王小虎5',
address: '上海市普陀区金沙江路 1516 弄'
// hasChildren: true
}
]
}
},
created() {},
methods: {
setChildren(children, type) {
// 编辑多个子层级
children.map(j => {
this.toggleSelection(j, type)
if (j.children) {
this.setChildren(j.children, type)
}
})
},
// 选中父节点时,子节点一起选中取消
select(selection, row) {
const hasSelect = selection.some(el => {
return row.id === el.id
})
if (hasSelect) {
if (row.children) {
// 解决子组件没有被勾选到
this.setChildren(row.children, true)
}
} else {
if (row.children) {
this.setChildren(row.children, false)
}
}
},
toggleSelection(row, select) {
if (row) {
this.$nextTick(() => {
this.$refs.multipleTable &&
this.$refs.multipleTable.toggleRowSelection(row, select)
})
}
},
// 选择全部
selectAll(selection) {
// tabledata第一层只要有在selection里面就是全选
const isSelect = selection.some(el => {
const tableDataIds = this.tableData.map(j => j.id)
return tableDataIds.includes(el.id)
})
// tableDate第一层只要有不在selection里面就是全不选
const isCancel = !this.tableData.every(el => {
const selectIds = selection.map(j => j.id)
return selectIds.includes(el.id)
})
if (isSelect) {
selection.map(el => {
if (el.children) {
// 解决子组件没有被勾选到
this.setChildren(el.children, true)
}
})
}
if (isCancel) {
this.tableData.map(el => {
if (el.children) {
// 解决子组件没有被勾选到
this.setChildren(el.children, false)
}
})
}
},
selectionChange(val) {
console.log(val)
},
async loadSearch(row, treeNode, resolve) {
this.maps.set(row.id, { row, treeNode, resolve })
const loadData = [
{
id: 3100,
parentId: 32,
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
},
{
id: 3200,
parentId: 32,
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}
]
await setTimeout(() => {
resolve(loadData)
}, 2000)
await this.setNewRowData(row, loadData)
},
setNewRowData(row, loadData) {
row.children = loadData
},
// 重新触发树形表格的loadSearch函数(因项目中需要多次触发loadTree方法,故封装成一个方法)
refreshLoadTree(parentId) {
// 根据父级id取出对应节点数据
const { row, treeNode, resolve } = this.maps.get(parentId)
this.$set(
this.$refs.multipleTable.store.states.lazyTreeNodeMap,
parentId,
[]
)
if (row) {
// 个人为了验证删除后的重新加载,这边触发的是 loadSearch2()函数。实际开发中应触发loadSearch() 函数
this.loadSearch2(row, treeNode, resolve)
}
},
handleClick(row) {
const { parentId } = row
this.refreshLoadTree(parentId)
},
handleAdd(row) {
const { id } = row
console.log(id)
// 注意:当新增的时候,要取当前的 id 作为其子集的 parentId,这里就不再以例子书写,最后都会用到上述方法 refreshLoadTree(parentId)
},
async loadSearch2(row, treeNode, resolve) {
this.maps.set(row.id, { row, treeNode, resolve })
const loadData = [
{
id: 3200,
parentId: 32,
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}
]
await setTimeout(() => {
resolve(loadData)
}, 2000)
await this.setNewRowData(row, loadData)
console.log('tabledata', this.tableData)
}
}
}
</script>
希望能够帮助到您,感谢您的支持!!!🙏拜托
上一篇:第九篇 Elementui 树形表格多选问题-多级树形表格懒加载复选框勾选问题