React DevExtreme DataGrid批量编辑模式下获取单元格变更列与新值问题
React DevExtreme DataGrid 批量+虚拟滚动模式下获取单元格变更信息
问题描述
使用React DevExtreme DataGrid,开启**批量编辑(batch)和虚拟滚动(virtual scrolling)**模式,尝试onKeyDown、onColumnsChange、onEditingChange等事件均无法获取变更的列及新值;使用onChangesChange函数但效果不符合预期。
相关代码如下:
DataGrid组件代码
<DataGrid scrolling={{ mode: "virtual" }} id={'id'} dataSource={dataDateGrid} onKeyDown={handleKeyDown} onColumnsChange={val => { console.log('onColumnsChange', val) }} onEditingChange={val => { console.log('onEditingChange', val) }} > <Editing mode="batch" allowUpdating /> </DataGrid>
尝试的handleChangesChange函数
const handleChangesChange = (changes: any) => { if (changes.length > 0) { // 尝试通过对比之前的变更记录找最新变更 const latestChange = changes.find( (change: any) => !previousChangesRef.current.includes(change) ); if (latestChange) { const { type, data, key, oldData } = latestChange; if (type === 'update') { // 遍历data找变更列 for (const column in data) { console.log('column: ', column); console.log('data: ', data); } } previousChangesRef.current = changes; } } }
解决方案
1. 正确绑定onChangesChange事件
首先要确保在DataGrid上正确绑定onChangesChange事件,补全组件属性:
<DataGrid scrolling={{ mode: "virtual" }} id={'id'} dataSource={dataDateGrid} // 绑定变更监听事件 onChangesChange={handleChangesChange} > <Editing mode="batch" allowUpdating /> </DataGrid>
2. 修正handleChangesChange逻辑
原代码通过includes对比变更项的方式不可行,因为每次变更后changes数组内的对象是新引用,无法通过引用匹配。正确做法是对比变更的key和类型,筛选出新增的变更:
import { useRef } from 'react'; // 用ref存储上次的变更记录 const previousChangesRef = useRef<any[]>([]); const handleChangesChange = (currentChanges: any[]) => { // 筛选出当前变更中未在上次记录出现的项 const newChanges = currentChanges.filter(currentChange => { return !previousChangesRef.current.some(prevChange => { return prevChange.key === currentChange.key && prevChange.type === currentChange.type; }); }); newChanges.forEach(change => { if (change.type === 'update') { // 对比oldData和data,找出真正变更的列 const changedColumns = Object.keys(change.data).filter(column => { return change.data[column] !== change.oldData[column]; }); changedColumns.forEach(column => { console.log(`变更列:${column}`); console.log(`新值:${change.data[column]}`); console.log(`旧值:${change.oldData[column]}`); console.log(`行唯一标识:${change.key}`); }); } }); // 更新上次变更记录,注意解构避免引用同步 previousChangesRef.current = [...currentChanges]; };
3. 备选方案:实时监听单元格编辑
如果需要在用户输入过程中实时获取变更(无需等待单元格失焦),可以通过onEditorPreparing绑定编辑器的onValueChanged事件:
<DataGrid scrolling={{ mode: "virtual" }} id={'id'} dataSource={dataDateGrid} onEditorPreparing={(e) => { if (e.parentType === 'dataRow' && e.dataField) { // 保留编辑器原有逻辑 const originalOnValueChanged = e.editorOptions.onValueChanged; e.editorOptions.onValueChanged = (args) => { originalOnValueChanged?.(args); // 输出变更信息 console.log(`变更列:${e.dataField}`); console.log(`新值:${args.value}`); console.log(`旧值:${args.previousValue}`); console.log(`当前行数据:${e.row.data}`); }; } }} > <Editing mode="batch" allowUpdating /> </DataGrid>
注意事项
- 虚拟滚动模式下,
onEditorPreparing仅在单元格编辑器创建时触发,符合按需渲染的逻辑。 - 批量模式下,
onChangesChange会在单元格编辑完成(如失焦、按回车)时触发,收集所有未提交的变更记录。
内容的提问来源于stack exchange,提问作者alaa-sufi
相关产品推荐
相关产品推荐

