From 35153f832338ea4b2744c9882a18c5873d517540 Mon Sep 17 00:00:00 2001 From: "ouxiaofeng.utlf" Date: Wed, 30 Sep 2026 18:44:56 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E7=BB=99=E8=A1=A8=E6=A0=BC?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=80=E4=B8=AA=E9=85=8D=E7=BD=AE=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vtable/__tests__/visual/cases/index.mjs | 2 + .../resize-column-non-realtime.mjs | 66 +++++++++++++++++ .../resize-column-realtime-default.mjs | 60 +++++++++++++++ .../examples/interactive/resize-realtime.ts | 73 +++++++++++++++++++ packages/vtable/examples/menu.ts | 4 + packages/vtable/src/core/BaseTable.ts | 2 + .../scenegraph/component/table-component.ts | 19 +++-- .../src/state/resize/update-resize-column.ts | 50 ++++++++----- .../src/state/resize/update-resize-row.ts | 31 ++++++++ packages/vtable/src/state/state.ts | 28 +++++-- packages/vtable/src/ts-types/base-table.ts | 9 +++ 11 files changed, 314 insertions(+), 30 deletions(-) create mode 100644 packages/vtable/__tests__/visual/cases/interaction/resize-column-non-realtime.mjs create mode 100644 packages/vtable/__tests__/visual/cases/interaction/resize-column-realtime-default.mjs create mode 100644 packages/vtable/examples/interactive/resize-realtime.ts diff --git a/packages/vtable/__tests__/visual/cases/index.mjs b/packages/vtable/__tests__/visual/cases/index.mjs index 1072fdd97c..769456ee9d 100644 --- a/packages/vtable/__tests__/visual/cases/index.mjs +++ b/packages/vtable/__tests__/visual/cases/index.mjs @@ -162,6 +162,8 @@ export const cases = [ { id: 'pivot-empty-string-dimension', purpose: '透视空字符串列维度与普通列并存', file: './pivot/empty-string-dimension.mjs', bundles: ['vtable'] }, { id: 'pivot-chart-pie-multi-select', purpose: '透视饼图连续扇区多选', file: './pivot-chart/pie-multi-select.mjs', bundles: ['vchart'] }, { id: 'resize-row-height', purpose: '列表选择后拖动行边界调整行高', file: './interaction/resize-row-height.mjs', bundles: ['vtable'] }, + { id: 'resize-column-non-realtime', purpose: 'resize.realtime=false 时列宽仅在鼠标松开后应用', file: './interaction/resize-column-non-realtime.mjs', bundles: ['vtable'] }, + { id: 'resize-column-realtime-default', purpose: 'resize.realtime 默认 true 时列宽实时随拖拽变化', file: './interaction/resize-column-realtime-default.mjs', bundles: ['vtable'] }, { id: 'pivot-resize-indicator-row', purpose: '指标行上的透视表拖动行高', file: './pivot/resize-indicator-row.mjs', bundles: ['vtable'] }, { id: 'pivot-corner-sort-one-dimension', purpose: '单级角头维度初始降序状态与排序图标', file: './pivot/corner-sort-one-dimension.mjs', bundles: ['vtable'] }, { id: 'pivot-corner-sort-two-dimensions', purpose: '两级角头维度初始降序状态与排序图标', file: './pivot/corner-sort-two-dimensions.mjs', bundles: ['vtable'] }, diff --git a/packages/vtable/__tests__/visual/cases/interaction/resize-column-non-realtime.mjs b/packages/vtable/__tests__/visual/cases/interaction/resize-column-non-realtime.mjs new file mode 100644 index 0000000000..74f74c57b2 --- /dev/null +++ b/packages/vtable/__tests__/visual/cases/interaction/resize-column-non-realtime.mjs @@ -0,0 +1,66 @@ +/** + * 验证目的:resize.realtime=false 时,列宽调整仅在鼠标松开后应用一次。 + * 拖拽过程中列宽保持不变,松开鼠标时列宽等于累计偏移量。 + */ +export default { + mount(container) { + return new window.VTable.ListTable(container, { + columns: [ + { field: 'name', title: 'Name', width: 150 }, + { field: 'value', title: 'Value', width: 150 } + ], + records: Array.from({ length: 5 }, (_, index) => ({ + name: `Item ${index + 1}`, + value: index + 1 + })), + defaultRowHeight: 32, + resize: { columnResizeMode: 'all', realtime: false } + }); + }, + async exercise(page) { + const point = await page.evaluate(() => { + const table = window.__visualTable; + const b = table.getCellRect(0, 0).bounds; + const host = document.getElementById('table').getBoundingClientRect(); + window.__colWidthBefore = table.getColWidth(0); + return { + cell: { x: host.x + (b.x1 + b.x2) / 2, y: host.y + (b.y1 + b.y2) / 2 }, + edge: { x: host.x + b.x2 - 1, y: host.y + (b.y1 + b.y2) / 2 } + }; + }); + await page.mouse.move(point.edge.x, point.edge.y); + await page.mouse.down(); + // 拖拽过程中每步都记录列宽,确认拖拽时列宽未变化 + await page.mouse.move(point.edge.x + 40, point.edge.y, { steps: 10 }); + const widthDuringDrag = await page.evaluate(() => window.__visualTable.getColWidth(0)); + await page.mouse.move(point.edge.x + 80, point.edge.y, { steps: 10 }); + const widthDuringDrag2 = await page.evaluate(() => window.__visualTable.getColWidth(0)); + await page.mouse.up(); + await page.evaluate( + ({ w1, w2 }) => { + window.__widthDuringDrag = w1; + window.__widthDuringDrag2 = w2; + }, + { w1: widthDuringDrag, w2: widthDuringDrag2 } + ); + }, + async verify(page) { + await page.evaluate(() => { + const table = window.__visualTable; + const before = window.__colWidthBefore; + const during1 = window.__widthDuringDrag; + const during2 = window.__widthDuringDrag2; + const after = table.getColWidth(0); + // 拖拽中列宽不应变化 + if (during1 !== before || during2 !== before) { + throw new Error( + `非实时响应模式下拖拽过程中列宽发生了变化: before=${before}, during1=${during1}, during2=${during2}, after=${after}` + ); + } + // 松开鼠标后列宽应增加(累计偏移量 80px 应用) + if (after <= before + 40) { + throw new Error(`鼠标松开后列宽未按累计偏移量应用: before=${before}, after=${after}`); + } + }); + } +}; diff --git a/packages/vtable/__tests__/visual/cases/interaction/resize-column-realtime-default.mjs b/packages/vtable/__tests__/visual/cases/interaction/resize-column-realtime-default.mjs new file mode 100644 index 0000000000..9cb7cc3f77 --- /dev/null +++ b/packages/vtable/__tests__/visual/cases/interaction/resize-column-realtime-default.mjs @@ -0,0 +1,60 @@ +/** + * 验证目的:resize.realtime=true(默认)时保持历史行为,拖拽过程中列宽实时变化。 + * 作为 resize-column-non-realtime 的对照用例,防止改动回归默认行为。 + */ +export default { + mount(container) { + return new window.VTable.ListTable(container, { + columns: [ + { field: 'name', title: 'Name', width: 150 }, + { field: 'value', title: 'Value', width: 150 } + ], + records: Array.from({ length: 5 }, (_, index) => ({ + name: `Item ${index + 1}`, + value: index + 1 + })), + defaultRowHeight: 32, + resize: { columnResizeMode: 'all' } + }); + }, + async exercise(page) { + const point = await page.evaluate(() => { + const table = window.__visualTable; + const b = table.getCellRect(0, 0).bounds; + const host = document.getElementById('table').getBoundingClientRect(); + window.__colWidthBefore = table.getColWidth(0); + return { + edge: { x: host.x + b.x2 - 1, y: host.y + (b.y1 + b.y2) / 2 } + }; + }); + await page.mouse.move(point.edge.x, point.edge.y); + await page.mouse.down(); + await page.mouse.move(point.edge.x + 40, point.edge.y, { steps: 10 }); + const widthDuringDrag = await page.evaluate(() => window.__visualTable.getColWidth(0)); + await page.mouse.move(point.edge.x + 80, point.edge.y, { steps: 10 }); + const widthDuringDrag2 = await page.evaluate(() => window.__visualTable.getColWidth(0)); + await page.mouse.up(); + await page.evaluate( + ({ w1, w2 }) => { + window.__widthDuringDrag = w1; + window.__widthDuringDrag2 = w2; + }, + { w1: widthDuringDrag, w2: widthDuringDrag2 } + ); + }, + async verify(page) { + await page.evaluate(() => { + const before = window.__colWidthBefore; + const during1 = window.__widthDuringDrag; + const during2 = window.__widthDuringDrag2; + const after = window.__visualTable.getColWidth(0); + // 实时模式:拖拽中列宽应递增 + if (during1 <= before || during2 <= during1) { + throw new Error(`实时模式下列宽未随拖拽变化: before=${before}, during1=${during1}, during2=${during2}`); + } + if (after <= before + 40) { + throw new Error(`鼠标松开后列宽未达到预期: before=${before}, after=${after}`); + } + }); + } +}; diff --git a/packages/vtable/examples/interactive/resize-realtime.ts b/packages/vtable/examples/interactive/resize-realtime.ts new file mode 100644 index 0000000000..cf749f0ae6 --- /dev/null +++ b/packages/vtable/examples/interactive/resize-realtime.ts @@ -0,0 +1,73 @@ +import * as VTable from '../../src'; + +const ListTable = VTable.ListTable; +const CONTAINER_ID = 'vTable'; + +export function createTable() { + // 生成较大数据量,便于对比实时与非实时响应下的拖拽流畅度 + const records = Array.from({ length: 10000 }, (_, index) => ({ + id: index + 1, + name: `记录 ${index + 1}`, + dept: ['研发', '产品', '运营', '销售'][index % 4], + city: ['杭州', '北京', '上海', '成都', '广州'][index % 5], + score: Math.round(Math.random() * 100), + salary: Math.round(4000 + Math.random() * 20000) + })); + + const option: any = { + columns: [ + { field: 'id', title: 'ID', width: 80 }, + { field: 'name', title: '姓名', width: 160 }, + { field: 'dept', title: '部门', width: 120 }, + { field: 'city', title: '城市', width: 120 }, + { field: 'score', title: '评分', width: 120 }, + { field: 'salary', title: '薪资', width: 140 } + ], + records, + defaultRowHeight: 32, + resize: { + columnResizeMode: 'all', + rowResizeMode: 'all', + // 关键:设为 false 时,拖拽过程只移动指示线,鼠标松开后才应用列宽/行高变化, + // 可显著缓解大数据量下的拖拽卡顿。默认为 true,保持原有行为。 + realtime: false + } + }; + + const instance = new ListTable(document.getElementById(CONTAINER_ID)!, option); + (window as any).tableInstance = instance; + + // 提供简单的运行时切换按钮,便于对比两种模式的手感 + const bar = document.createElement('div'); + bar.style.cssText = [ + 'position:fixed', + 'top:10px', + 'right:10px', + 'z-index:9999', + 'background:#fff', + 'padding:8px 12px', + 'border:1px solid #ddd', + 'border-radius:4px', + 'box-shadow:0 1px 4px rgba(0,0,0,.1)', + 'font-family:sans-serif', + 'font-size:12px' + ].join(';'); + bar.innerHTML = ` +
当前 resize.realtime = false
+ + `; + document.body.appendChild(bar); + let current = false; + bar.querySelector('#__toggle_realtime')!.addEventListener('click', () => { + current = !current; + // 通过 updateOption 重新应用配置 + (instance as any).updateOption({ + ...option, + resize: { ...option.resize, realtime: current } + }); + (bar.querySelector('#__realtime_state') as HTMLElement).textContent = String(current); + (bar.querySelector('#__toggle_realtime') as HTMLElement).textContent = `切换为 ${ + current ? '非实时(false)' : '实时(true)' + }`; + }); +} diff --git a/packages/vtable/examples/menu.ts b/packages/vtable/examples/menu.ts index a6ad9e99ac..2a1ed18284 100644 --- a/packages/vtable/examples/menu.ts +++ b/packages/vtable/examples/menu.ts @@ -979,6 +979,10 @@ export const menus = [ path: 'interactive', name: 'row-resize' }, + { + path: 'interactive', + name: 'resize-realtime' + }, { path: 'interactive', name: 'resize-setRecords' diff --git a/packages/vtable/src/core/BaseTable.ts b/packages/vtable/src/core/BaseTable.ts index 8f880d7481..9ca2e75ad3 100644 --- a/packages/vtable/src/core/BaseTable.ts +++ b/packages/vtable/src/core/BaseTable.ts @@ -462,6 +462,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { internalProps.columnResizeMode = resize?.columnResizeMode ?? columnResizeMode; internalProps.canResizeColumn = resize?.canResizeColumn; internalProps.rowResizeMode = resize?.rowResizeMode ?? rowResizeMode; + internalProps.resizeRealtime = resize?.realtime !== false; internalProps.dragHeaderMode = dragOrder?.dragHeaderMode ?? dragHeaderMode ?? 'none'; internalProps.renderChartAsync = renderChartAsync; setBatchRenderChartCount(renderChartAsyncBatchCount); @@ -2911,6 +2912,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { internalProps.columnResizeMode = resize?.columnResizeMode ?? columnResizeMode; internalProps.canResizeColumn = resize?.canResizeColumn; internalProps.rowResizeMode = resize?.rowResizeMode ?? rowResizeMode; + internalProps.resizeRealtime = resize?.realtime !== false; internalProps.dragHeaderMode = dragOrder?.dragHeaderMode ?? dragHeaderMode ?? 'none'; internalProps.renderChartAsync = renderChartAsync; setBatchRenderChartCount(renderChartAsyncBatchCount); diff --git a/packages/vtable/src/scenegraph/component/table-component.ts b/packages/vtable/src/scenegraph/component/table-component.ts index 8352992d2c..33fae723b4 100644 --- a/packages/vtable/src/scenegraph/component/table-component.ts +++ b/packages/vtable/src/scenegraph/component/table-component.ts @@ -640,9 +640,12 @@ export class TableComponent { * @param {number} y 标签显示的y坐标 * @return {*} */ - updateResizeCol(col: number, y: number, isRightFrozen?: boolean) { + updateResizeCol(col: number, y: number, isRightFrozen?: boolean, previewDeltaX?: number) { // 基准线 - const colX = getColX(col, this.table, isRightFrozen); + const colBaseX = getColX(col, this.table, isRightFrozen); + const delta = previewDeltaX ?? 0; + // 非实时响应模式下指示线基于当前列右边界+累计偏移量渲染 + const colX = isRightFrozen ? colBaseX - delta : colBaseX + delta; // this.columnResizeLine.setAttribute('x', x); this.columnResizeLine.setAttributes({ x: colX, @@ -665,7 +668,8 @@ export class TableComponent { x: colX, y }); - (this.columnResizeLabel.lastChild as Text).setAttribute('text', `${Math.floor(this.table.getColWidth(col))}px`); + const previewWidth = Math.max(0, this.table.getColWidth(col) + delta); + (this.columnResizeLabel.lastChild as Text).setAttribute('text', `${Math.floor(previewWidth)}px`); } } @@ -725,9 +729,11 @@ export class TableComponent { * @param {number} y 标签显示的y坐标 * @return {*} */ - updateResizeRow(row: number, x: number, isBottomFrozen?: boolean) { + updateResizeRow(row: number, x: number, isBottomFrozen?: boolean, previewDeltaY?: number) { // 基准线 - const rowY = getRowY(row, this.table, isBottomFrozen); + const rowBaseY = getRowY(row, this.table, isBottomFrozen); + const delta = previewDeltaY ?? 0; + const rowY = isBottomFrozen ? rowBaseY - delta : rowBaseY + delta; // this.columnResizeLine.setAttribute('x', x); this.rowResizeLine.setAttributes({ y: rowY, @@ -750,7 +756,8 @@ export class TableComponent { y: rowY, x }); - (this.rowResizeLabel.lastChild as Text).setAttribute('text', `${Math.floor(this.table.getRowHeight(row))}px`); + const previewHeight = Math.max(0, this.table.getRowHeight(row) + delta); + (this.rowResizeLabel.lastChild as Text).setAttribute('text', `${Math.floor(previewHeight)}px`); } } diff --git a/packages/vtable/src/state/resize/update-resize-column.ts b/packages/vtable/src/state/resize/update-resize-column.ts index 7d7c7cf41e..4ba6ce55d5 100644 --- a/packages/vtable/src/state/resize/update-resize-column.ts +++ b/packages/vtable/src/state/resize/update-resize-column.ts @@ -14,15 +14,40 @@ export function updateResizeColumn(xInTable: number, yInTable: number, state: St return; } + // 非实时响应模式:仅累积偏移量并移动指示线,实际列宽在拖拽结束时统一应用 + if (state.table.internalProps.resizeRealtime === false) { + state.columnResize.pendingDeltaX = (state.columnResize.pendingDeltaX ?? 0) + detaX; + state.columnResize.x = xInTable; + state.table.scenegraph.component.updateResizeCol( + state.columnResize.col, + yInTable, + state.columnResize.isRightFrozen, + state.columnResize.pendingDeltaX + ); + state.table.scenegraph.updateNextFrame(); + return; + } + + applyColumnResizeDelta(detaX, xInTable, yInTable, state); +} + +/** 非实时响应模式下,在拖拽结束时提交累计的宽度变化 */ +export function commitPendingColumnResize(state: StateManager) { + const pending = state.columnResize.pendingDeltaX ?? 0; + state.columnResize.pendingDeltaX = 0; + if (Math.abs(pending) < 1) { + return; + } + // 用当前列坐标+累计偏移量作为最终位置,复用实时模式的处理逻辑 + const isRightFrozen = state.columnResize.isRightFrozen; + const currentX = state.columnResize.x; + const targetX = isRightFrozen ? currentX - pending : currentX + pending; + applyColumnResizeDelta(pending, targetX, currentX, state); +} + +function applyColumnResizeDelta(detaX: number, xInTable: number, yInTable: number, state: StateManager) { // 检查minWidth/maxWidth - // getColWidth会进行Math.round,所以先从colWidthsMap获取: - // 如果是数值,直接使用;如果不是,则通过getColWidth获取像素值 - // let widthCache = (state.table as any).colWidthsMap.get(state.columnResize.col); - // if (typeof widthCache === 'number') { - // widthCache = widthCache; - // } else { const widthCache = state.table.getColWidth(state.columnResize.col); - // } let width = widthCache; width += detaX; const minWidth = state.table.getMinColWidth(state.columnResize.col); @@ -80,17 +105,6 @@ export function updateResizeColumn(xInTable: number, yInTable: number, state: St updateResizeColForColumn(detaX, state); } - // if (state.table.widthMode === 'adaptive' && state.columnResize.col < state.table.colCount - 1) { - // // in adaptive mode, the right column width can not be negative - // const rightColWidth = state.table.getColWidth(state.columnResize.col + 1); - // if (rightColWidth - detaX < 0) { - // detaX = rightColWidth; - // } - // state.table.scenegraph.updateColWidth(state.columnResize.col, detaX); - // state.table.scenegraph.updateColWidth(state.columnResize.col + 1, -detaX); - // } else { - // state.table.scenegraph.updateColWidth(state.columnResize.col, detaX); - // } state.columnResize.x = xInTable; // update resize column component diff --git a/packages/vtable/src/state/resize/update-resize-row.ts b/packages/vtable/src/state/resize/update-resize-row.ts index 0d61f43790..3a358b426e 100644 --- a/packages/vtable/src/state/resize/update-resize-row.ts +++ b/packages/vtable/src/state/resize/update-resize-row.ts @@ -14,6 +14,37 @@ export function updateResizeRow(xInTable: number, yInTable: number, state: State return; } + // 非实时响应模式:仅累积偏移量并移动指示线,实际行高在拖拽结束时统一应用 + if (state.table.internalProps.resizeRealtime === false) { + state.rowResize.pendingDeltaY = (state.rowResize.pendingDeltaY ?? 0) + detaY; + state.rowResize.y = yInTable; + state.table.scenegraph.component.updateResizeRow( + state.rowResize.row, + xInTable, + state.rowResize.isBottomFrozen, + state.rowResize.pendingDeltaY + ); + state.table.scenegraph.updateNextFrame(); + return; + } + + applyRowResizeDelta(detaY, xInTable, yInTable, state); +} + +/** 非实时响应模式下,在拖拽结束时提交累计的高度变化 */ +export function commitPendingRowResize(state: StateManager) { + const pending = state.rowResize.pendingDeltaY ?? 0; + state.rowResize.pendingDeltaY = 0; + if (Math.abs(pending) < 1) { + return; + } + const isBottomFrozen = state.rowResize.isBottomFrozen; + const currentY = state.rowResize.y; + const targetY = isBottomFrozen ? currentY - pending : currentY + pending; + applyRowResizeDelta(pending, currentY, targetY, state); +} + +function applyRowResizeDelta(detaY: number, xInTable: number, yInTable: number, state: StateManager) { const heightCache = state.table.getRowHeight(state.rowResize.row); let height = heightCache; height += detaY; diff --git a/packages/vtable/src/state/state.ts b/packages/vtable/src/state/state.ts index b6af718f19..640cde7f2c 100644 --- a/packages/vtable/src/state/state.ts +++ b/packages/vtable/src/state/state.ts @@ -37,7 +37,7 @@ import { getIconAndPositionFromTarget } from '../scenegraph/utils/icon'; import type { BaseTableAPI, HeaderData } from '../ts-types/base-table'; import { getBodyHorizontalScrollRange } from '../scenegraph/component/util'; import { debounce } from '../tools/debounce'; -import { updateResizeColumn } from './resize/update-resize-column'; +import { updateResizeColumn, commitPendingColumnResize } from './resize/update-resize-column'; import { changeRadioOrder, setRadioState, syncRadioState } from './radio/radio'; import { changeCheckboxOrder, @@ -48,7 +48,7 @@ import { syncCheckedState, updateHeaderCheckedState } from './checkbox/checkbox'; -import { updateResizeRow } from './resize/update-resize-row'; +import { updateResizeRow, commitPendingRowResize } from './resize/update-resize-row'; import { deleteAllSelectingBorder } from '../scenegraph/select/delete-select-border'; import type { PivotTable } from '../PivotTable'; import { traverseObject } from '../tools/util'; @@ -135,6 +135,8 @@ export class StateManager { x: number; resizing: boolean; isRightFrozen?: boolean; + /** 非实时响应模式下,指示线相对原始列右边界的累计偏移量 */ + pendingDeltaX?: number; }; rowResize: { row: number; @@ -142,6 +144,8 @@ export class StateManager { y: number; resizing: boolean; isBottomFrozen?: boolean; + /** 非实时响应模式下,指示线相对原始行下边界的累计偏移量 */ + pendingDeltaY?: number; }; columnMove: { colSource: number; @@ -295,12 +299,14 @@ export class StateManager { this.columnResize = { col: -1, x: 0, - resizing: false + resizing: false, + pendingDeltaX: 0 }; this.rowResize = { row: -1, y: 0, - resizing: false + resizing: false, + pendingDeltaY: 0 }; this.columnMove = { colSource: -1, @@ -382,12 +388,14 @@ export class StateManager { this.columnResize = { col: -1, x: 0, - resizing: false + resizing: false, + pendingDeltaX: 0 }; this.rowResize = { row: -1, y: 0, - resizing: false + resizing: false, + pendingDeltaY: 0 }; this.columnMove = { colSource: -1, @@ -847,6 +855,9 @@ export class StateManager { } endResizeCol() { + if (this.columnResize.resizing && this.table.internalProps.resizeRealtime === false) { + commitPendingColumnResize(this); + } setTimeout(() => { this.columnResize.resizing = false; }, 0); @@ -860,6 +871,7 @@ export class StateManager { this.columnResize.col = col; this.columnResize.x = x; this.columnResize.isRightFrozen = isRightFrozen; + this.columnResize.pendingDeltaX = 0; this.table.scenegraph.component.showResizeCol(col, y, isRightFrozen); @@ -874,6 +886,9 @@ export class StateManager { } endResizeRow() { + if (this.rowResize.resizing && this.table.internalProps.resizeRealtime === false) { + commitPendingRowResize(this); + } setTimeout(() => { this.rowResize.resizing = false; }, 0); @@ -887,6 +902,7 @@ export class StateManager { this.rowResize.row = row; this.rowResize.y = y; this.rowResize.isBottomFrozen = isBottomFrozen; + this.rowResize.pendingDeltaY = 0; this.table.scenegraph.component.showResizeRow(row, x, isBottomFrozen); diff --git a/packages/vtable/src/ts-types/base-table.ts b/packages/vtable/src/ts-types/base-table.ts index 9c27788d55..32feb5ab1d 100644 --- a/packages/vtable/src/ts-types/base-table.ts +++ b/packages/vtable/src/ts-types/base-table.ts @@ -145,6 +145,9 @@ export interface IBaseTableProtected { rowResizeMode?: 'all' | 'none' | 'header' | 'body'; + /** 拖拽调整行列尺寸时是否实时响应,为 false 时仅拖拽结束后应用尺寸变化 */ + resizeRealtime?: boolean; + columnResizeType?: 'column' | 'indicator' | 'all' | 'indicatorGroup'; rowResizeType?: 'row' | 'indicator' | 'all' | 'indicatorGroup'; @@ -720,6 +723,12 @@ export interface BaseTableConstructorOptions { rowResizeMode?: 'all' | 'none' | 'header' | 'body'; /** 是否禁用双击列边框自动调整列宽 **/ disableDblclickAutoResizeColWidth?: boolean; + /** + * 拖拽调整行列尺寸时是否实时响应。 + * true(默认):拖拽过程中实时更新列宽/行高,与历史行为一致。 + * false:拖拽过程中仅移动指示线,鼠标释放时才应用最终尺寸变化,可缓解大数据量场景下的拖拽卡顿。 + */ + realtime?: boolean; }; dragOrder?: { /** 控制拖拽表头移动位置顺序开关 */ From 1ea2e954fb3cae53feb2c5da2ce0f94d2623b1e3 Mon Sep 17 00:00:00 2001 From: "ouxiaofeng.utlf" Date: Wed, 30 Sep 2026 18:49:16 +0800 Subject: [PATCH 2/2] feat: update doc --- docs/assets/option/en/common/option-secondary.md | 7 +++++++ docs/assets/option/zh/common/option-secondary.md | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/docs/assets/option/en/common/option-secondary.md b/docs/assets/option/en/common/option-secondary.md index abc43c2089..4d3227f667 100644 --- a/docs/assets/option/en/common/option-secondary.md +++ b/docs/assets/option/en/common/option-secondary.md @@ -721,6 +721,13 @@ Whether to adjust the column width, support configuring functions, the function canResizeColumn?: (col: number, row: number, table: BaseTableAPI) => boolean; ``` +##${prefix} realtime(boolean) = true + +Whether to respond in real time when dragging to resize columns/rows. + +- `true` (default): Column widths / row heights update in real time during dragging, keeping the historical behavior. +- `false`: Only the indicator line moves while dragging; the final size is applied when the mouse is released. Recommended for large datasets to significantly reduce lag while dragging. + #${prefix} dragOrder(Object) #${prefix} dragOrder(Object) diff --git a/docs/assets/option/zh/common/option-secondary.md b/docs/assets/option/zh/common/option-secondary.md index cc560547bf..b96f8471f2 100644 --- a/docs/assets/option/zh/common/option-secondary.md +++ b/docs/assets/option/zh/common/option-secondary.md @@ -719,6 +719,13 @@ animationAppear?: boolean | { canResizeColumn?: (col: number, row: number, table: BaseTableAPI) => boolean; ``` +##${prefix} realtime(boolean) = true + +拖拽调整行列尺寸时是否实时响应。 + +- `true`(默认):拖拽过程中实时更新列宽/行高,与历史行为一致。 +- `false`:拖拽过程中仅移动指示线,鼠标释放后才应用最终尺寸变化。适用于大数据量场景,可显著缓解拖拽时的卡顿。 + #${prefix} dragOrder(Object) 拖拽移动位置的配置。