fix(grid): avoid repeated search text allocations

This commit is contained in:
vrustx authored and GitHub committed 2026-07-18 21:40:08 +08:00
1 parent 9020a4dd51
commit bd7065f244
6 files changed
+134 -12

No files matched your search

+10 -5
View File
@@ -131,7 +131,8 @@ import { dataGridHeaderContentWidth, scrollbarGutterWidth } from "@/lib/dataGrid
import { canGoNextDataGridPage } from "@/lib/dataGrid/dataGridPagination";
import { dataGridCountQueryOptions } from "@/lib/dataGrid/dataGridQueryOptions";
import { dataGridBottomScrollTop, dataGridScrollPosition, isDataGridAtScrollBottom, isDataGridNearScrollBottom, shouldCheckInfiniteScrollAfterScroll, type DataGridScrollPosition } from "@/lib/dataGrid/dataGridInfiniteScroll";
import { CANVAS_DATA_GRID_ROW_HEIGHT, drawCanvasDataGrid } from "@/lib/dataGrid/canvasDataGridRenderer";
import { CANVAS_DATA_GRID_ROW_HEIGHT, dataGridSearchMatchKey, drawCanvasDataGrid } from "@/lib/dataGrid/canvasDataGridRenderer";
import { createRowLowerTextCache } from "@/lib/dataGrid/dataGridRowLowerText";
import { dataGridPreviewLabelKey, dataGridSaveActionMode, dataGridSaveToolbarState } from "@/lib/dataGrid/dataGridSaveUi";
import type { QueryEditabilityReason } from "@/lib/sql/sqlAnalysis";
import { EDITOR_FONT_FAMILY_CSS_VAR } from "@/lib/editor/editorThemes";
@@ -558,7 +559,7 @@ const dataGridSearch = useDataGridSearch({
columns: () => props.result.columns,
suggestionColumns: () => props.tableMeta?.columns.map((column) => column.name) ?? props.result.columns,
rows: () => displayItems.value,
getCellText: (row, columnIndex) => (row.data[columnIndex] === null ? "" : formatCellCached(row.data[columnIndex], columnIndex)),
getCellSearchText: (row, columnIndex) => (row.data[columnIndex] === null ? "" : rowLowerTextCache.get(row.data, columnIndex)),
onNavigate: () => nextTick(scrollToCurrentMatch),
});
const { searchText, deferredSearchText: deferredClientSearchText, overlayVisible: searchOverlayVisible, currentMatchIndex, suggestions: searchSuggestions, suggestionIndex, matches: searchMatches, matchSet: searchMatchSet, currentMatch: currentSearchMatch } = dataGridSearch;
@@ -3061,7 +3062,7 @@ const sortedRows = computed(() => {
const rows = props.result.rows;
indices = indices.filter((sourceIndex) => {
const data = rows[sourceIndex];
return data.some((cell, columnIndex) => cell !== null && formatCellCached(cell, columnIndex).toLowerCase().includes(q));
return data.some((cell, columnIndex) => cell !== null && rowLowerTextCache.get(data, columnIndex).includes(q));
});
}
return indices;
@@ -3203,7 +3204,7 @@ watch(
function cellIsSearchMatch(displayRow: number, col: number): boolean {
if (isScrolling.value) return false;
return searchMatchSet.value.has(`cell:${displayRow}:${col}`);
return searchMatchSet.value.has(dataGridSearchMatchKey(displayRow, col));
}
function cellIsCurrentMatch(displayRow: number, col: number): boolean {
@@ -3217,7 +3218,7 @@ function cellIsCurrentMatch(displayRow: number, col: number): boolean {
// maps to the field row header at the field's column index.
function transposeHeaderIsSearchMatch(fieldIndex: number): boolean {
if (isScrolling.value) return false;
return searchMatchSet.value.has(`column:-1:${fieldIndex}`);
return searchMatchSet.value.has(dataGridSearchMatchKey(-1, fieldIndex));
}
function transposeHeaderIsCurrentMatch(fieldIndex: number): boolean {
@@ -4148,6 +4149,9 @@ const resolvedColumnFormatters = computed(() => props.result.columns.map((_, col
const columnFormatterSignatures = computed(() => resolvedColumnFormatters.value.map(formatterSignature));
const primitiveCellFormatCache = new Map<string, string>();
let objectCellFormatCache = new WeakMap<object, Map<number, string>>();
// 搜索用小写文本缓存:按行数组身份挂 WeakMap(工作集=当前结果行,GC 回收),
// 不用固定容量 LRU——搜索是全量顺序扫描,超限修剪会导致第二遍零命中抖动
const rowLowerTextCache = createRowLowerTextCache(formatCellCached);
function formatterSignature(formatter: ColumnFormatterConfig | undefined): string {
return formatter ? JSON.stringify(formatter) : "";
@@ -4156,6 +4160,7 @@ function formatterSignature(formatter: ColumnFormatterConfig | undefined): strin
function clearCellFormatCache() {
primitiveCellFormatCache.clear();
objectCellFormatCache = new WeakMap<object, Map<number, string>>();
rowLowerTextCache.clear();
}
function rememberPrimitiveCellFormat(key: string, display: string): string {