背景
最近的一个新项目需要用到大数据表格编辑,苦于在elementUI
中的table
控件不支持虚拟滚动和对表格内编辑不友好,我们只能寻求其它支持大数据展示的控件库,最后选用了umy-ui
进行前端大数据表格开发。而最近在使用表格编辑时候看到了有获取编辑行的方法(getUpdateRecords
),但由于我们可能会多个人同时编辑一行但是不同列的原因,不允许直接把当前行的结果进行提交,然而我没有在官方文档找到获取已编辑列的方法,于是就按自己的想法来实现该需求。因为有些人仅需要实现方案,所以下面优先给出解决方案再说明我的解决思路以供参考。
展示效果
-
页面打开样式,编辑前
-
编辑4个单元格
-
提交输出
解决方案
<template>
<div>
<el-row>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-finished"
size="mini"
@click="handleSave"
>保存改动</el-button>
</el-col>
</el-row>
<ux-grid ref="table" use-virtual border height="430px"
:edit-config="{trigger: 'click', mode: 'cell'}"
big-data-checkbox show-overflow="title"
keep-source @edit-closed="editClosed">
<ux-table-column type="checkbox" width="55" align="center" />
<ux-table-column type="index" width="60" title="序号" align="center" />
<template v-for="item in columns">
<ux-table-column
:key="item.field" :field="item.field"
:title="item.title" align="center" width="100"
edit-render>
<!-- 可编辑的单元格需要使用v-slot:edit -->
<template v-slot:edit="scope">
<el-input v-model="scope.row['field']"></el-input>
</template>
</ux-table-column>
</template>
</ux-grid>
</div>
</template>
<script>
export default {
name: "Test",
created() {
// 在组件打开时就进行数据查询
this.getList();
},
data() {
return {
// 编辑过的单元格, key为ID值, value为列名称对象, 避免提交修改一整行
editColumns: {},
// 表格的列
columns: [{
field: 'field1',
title: '字段1'
},{
field: 'field2',
title: '字段2'
},{
field: 'field3',
title: '字段3'
},{
field: 'field4',
title: '字段4'
},{
field: 'field5',
title: '字段5'
}
]
}
},
methods: {
/** 查询数据 */
getList() {
// 每次重新查询时, 将数据编辑记录清空
this.editColumns = {};
this.$nextTick(() => {
let dataList = [];
for (let i = 0; i < 500; i++) {
dataList.push({
id: i,
field1: `field1_${i}`,
field2: `field2_${i}`,
field3: `field3_${i}`,
field4: `field4_${i}`,
field5: `field5_${i}`,
})
}
this.$refs.table.reloadData(dataList);
// 大数据测试表格数据, 此变量不写入data()
this.bigDataDemoList = dataList;
// 备份原数据, 避免修改后无法对比是否更改, 此变量不写入data()
this.sourceTableData = JSON.parse(JSON.stringify(this.bigDataDemoList));
})
},
/** 保存数据 */
handleSave() {
let editRows = this.$refs.table.getUpdateRecords();
if (editRows.length == 0) {
this.$modal.msgWarning("没有修改的行");
return;
}
// 遍历更新行, 只将编辑的列进行提交
let submitEditDatas = [];
editRows.forEach(row => {
let submitEditData = {};
submitEditData.id = row.id;
// 只将编辑的列进行提交
for (let key in this.editColumns[row.id]) {
submitEditData[key] = this.editColumns[row.id][key]
}
submitEditDatas.push(submitEditData);
});
console.log("提交的数据", submitEditDatas);
this.$message.success("修改成功")
},
/** 表格编辑完毕时*/
editClosed(event) {
let row = event.row;
let prop = event.column.property;
// 记录下已变更的字段
let sourceTableRowData = this.sourceTableData.find(item => item.id === row.id);
if (row[prop] !== sourceTableRowData[prop]) {
if (this.editColumns[row.id] == null) {
this.editColumns[row.id] = {};
}
this.editColumns[row.id][prop] = row[prop];
return;
}
// 如果还原了列值, 则将对象中的key删除, 避免在提交时仍遍历了该属性
let isRevertFieldVal = this.editColumns[row.id] != null && this.editColumns[row.id].hasOwnProperty(prop);
if (isRevertFieldVal) {
delete this.editColumns[row.id][prop];
}
}
}
}
</script>
解决问题的思路
- 通过查找官方文档获取编辑列的方法,但是找不着,只能获取编辑行
getUpdateRecords
,放弃 - 使用
编辑激活事件(edit-actived)
和全局变量记录下当前单元格的值,然后在编辑完成事件(edit-closed)
与记录的变化对象进行比较,如果不同的就记录该列是产生变化的,在submit
中取编辑行并遍历列改变量取到修改的列进行提交,但是存在的问题是如果原始值是a
,我把单元格的值改成b
后再改成a依然会记录是已修改的值, 放弃 - 在表格数据查出来后将数据克隆到全局变量中,这样我们能在
edit-closed
与原始值做比较(要是能直接通过表格获取原始值就好了- -||,因为启用了keep-source
是会克隆原始值的,但是api中并未提供获取方法,只能自己又克隆一遍),在每次编辑完成事件记录下改变的字段值,如果用户将值修改为与原始值相同的时候,清楚记录值。 - PS:如果有找到api中有提供修改列,可以留个言告知一下哈