fix(grid): avoid repeated search text allocations
This commit is contained in:
1 parent
9020a4dd51
commit
bd7065f244
6 files changed
+134
-12
No files matched your search
@@ -25,6 +25,13 @@ export interface CanvasEditingCell {
|
||||
col: number;
|
||||
}
|
||||
|
||||
/** 搜索匹配的数值 key:列头匹配 displayRow 为 -1。相比字符串拼接 key,
|
||||
* 每次按键构建 matchSet、每帧对可见单元格查询都零字符串分配。
|
||||
* ponytail: 列数上限 65536,网格列数远达不到 */
|
||||
export function dataGridSearchMatchKey(displayRow: number, col: number): number {
|
||||
return (displayRow + 1) * 65536 + col;
|
||||
}
|
||||
|
||||
export interface CanvasSearchMatch {
|
||||
kind: "cell" | "column";
|
||||
displayRow: number;
|
||||
@@ -50,7 +57,7 @@ export interface DrawCanvasDataGridOptions {
|
||||
hoverCell: CanvasHoverCell | null;
|
||||
isScrolling: boolean;
|
||||
editingCell: CanvasEditingCell | null;
|
||||
searchMatchKeys: ReadonlySet<string>;
|
||||
searchMatchKeys: ReadonlySet<number>;
|
||||
currentSearchMatch: CanvasSearchMatch | null;
|
||||
formatCell: (value: CellValue, columnIndex: number) => string;
|
||||
draftCellPlaceholder?: string;
|
||||
@@ -334,7 +341,7 @@ export function drawCanvasDataGrid(options: DrawCanvasDataGridOptions) {
|
||||
const isDirtyCell = item.isDirtyCol[actualColIdx];
|
||||
const selectedFillVisual = rowSelectionVisual || selectedCell;
|
||||
const selectedBorderVisual = rowSelectionVisual || selectedCell;
|
||||
const isSearchMatch = paintSearchMatches && searchMatchKeys.has(`cell:${item.displayIndex}:${actualColIdx}`);
|
||||
const isSearchMatch = paintSearchMatches && searchMatchKeys.has(dataGridSearchMatchKey(item.displayIndex, actualColIdx));
|
||||
const isCurrentSearchMatch = paintSearchMatches && currentSearchMatch?.displayRow === item.displayIndex && currentSearchMatch.col === actualColIdx;
|
||||
const clippedX = Math.max(drawX, rowNumberWidth);
|
||||
const cellPaintWidth = Math.min(width, drawX + colWidth) - clippedX;
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import type { CellValue } from "@/lib/dataGrid/cellValue";
|
||||
|
||||
type RowLowerTextEntry = {
|
||||
/** 每列缓存时的源值引用:单元格被原地编辑后引用不再相等,仅重算该格 */
|
||||
values: CellValue[];
|
||||
lowers: (string | undefined)[];
|
||||
};
|
||||
|
||||
/**
|
||||
* 搜索用小写文本缓存,按行数组身份挂 WeakMap:
|
||||
* - 工作集天然等于当前在内存中的结果行(行数组是 markRaw 的稳定引用),
|
||||
* 不存在固定容量 LRU 在全量顺序扫描下的零命中抖动,GC 自动回收旧结果;
|
||||
* - 展示格式化器/列类型变化时由调用方 clear() 整体失效。
|
||||
*/
|
||||
export function createRowLowerTextCache(format: (value: CellValue, columnIndex: number) => string) {
|
||||
let cache = new WeakMap<object, RowLowerTextEntry>();
|
||||
|
||||
function get(rowData: CellValue[], columnIndex: number): string {
|
||||
let entry = cache.get(rowData);
|
||||
if (!entry) {
|
||||
entry = { values: [], lowers: [] };
|
||||
cache.set(rowData, entry);
|
||||
}
|
||||
const value = rowData[columnIndex];
|
||||
const cached = entry.lowers[columnIndex];
|
||||
if (cached !== undefined && Object.is(entry.values[columnIndex], value)) return cached;
|
||||
const lower = format(value, columnIndex).toLowerCase();
|
||||
entry.values[columnIndex] = value;
|
||||
entry.lowers[columnIndex] = lower;
|
||||
return lower;
|
||||
}
|
||||
|
||||
function clear() {
|
||||
cache = new WeakMap<object, RowLowerTextEntry>();
|
||||
}
|
||||
|
||||
return { get, clear };
|
||||
}
|
||||
Reference in new issue
Block a user