@@ -201,11 +201,28 @@ function sortHeader(header: TableHeader) {
201201 emit (' update:sort' , sort )
202202}
203203
204+ const pathCache = new Map <string , string []>()
205+
204206function getValue(item : T , path : string | string [] | undefined ): unknown {
205207 if (! path ) return ' '
206208 if (! item ) return ' '
207209
208- const pathArray = Array .isArray (path ) ? path : path .match (/ ([^ [. \] ] )+ / g )
210+ let pathArray: string [] | null
211+
212+ if (Array .isArray (path )) {
213+ pathArray = path
214+ } else {
215+ // Check cache first
216+ if (pathCache .has (path )) {
217+ pathArray = pathCache .get (path )!
218+ } else {
219+ // Parse and cache the result
220+ pathArray = path .match (/ ([^ [. \] ] )+ / g )
221+ if (pathArray ) {
222+ pathCache .set (path , pathArray )
223+ }
224+ }
225+ }
209226
210227 if (! pathArray || pathArray .length === 0 ) return ' '
211228
@@ -225,34 +242,55 @@ const allKeys = computed<(number | string)[]>(() => {
225242 return items .value .map ((item , index ) => getItemKey (item , index ))
226243})
227244
245+ const selectedSet = computed (() => {
246+ if (! props .selectable || props .singleSelect ) return new Set <number | string >()
247+ if (! Array .isArray (selected .value )) return new Set <number | string >()
248+
249+ return new Set (selected .value )
250+ })
251+
228252const allRowsSelected = computed (() => {
229253 if (! props .selectable || props .singleSelect ) return false
254+ if (! Array .isArray (selected .value ) || selected .value .length === 0 ) return false
255+
256+ const keysLength = allKeys .value .length
257+
258+ if (keysLength === 0 ) return false
230259
231- return Array . isArray ( selected .value ) && selected . value . length > 0 && allKeys . value . length > 0 && selected . value . length === allKeys . value . length
260+ return selected .value . length === keysLength
232261})
233262
234263const someRowsSelected = computed (() => {
235264 if (! props .selectable || props .singleSelect ) return false
265+ if (! Array .isArray (selected .value ) || selected .value .length === 0 ) return false
236266
237- return Array .isArray (selected .value ) && selected .value .length > 0 && allKeys .value .length > 0 && selected .value .length !== allKeys .value .length
267+ const keysLength = allKeys .value .length
268+
269+ if (keysLength === 0 ) return false
270+
271+ return selected .value .length > 0 && selected .value .length !== keysLength
238272})
239273
240274function isRowSelected(rowKey : number | string ): boolean {
241275 if (! props .selectable ) return false
276+
242277 if (props .singleSelect ) {
243278 return selected .value === rowKey
244- } else {
245- return Array .isArray (selected .value ) && selected .value .includes (rowKey )
246279 }
280+
281+ return selectedSet .value .has (rowKey )
247282}
248283
249284function toggleRowSelection(rowKey : number | string ) {
250285 if (! props .selectable ) return
286+
251287 if (props .singleSelect ) {
252288 selected .value = selected .value === rowKey ? undefined : rowKey
253289 } else {
254290 if (! Array .isArray (selected .value )) selected .value = []
255- if (selected .value .includes (rowKey )) {
291+
292+ // Use Set for O(1) lookup instead of includes O(n)
293+ if (selectedSet .value .has (rowKey )) {
256294 selected .value = selected .value .filter ((k : number | string ) => k !== rowKey )
257295 } else {
258296 selected .value = [... selected .value , rowKey ]
@@ -308,30 +346,30 @@ const columnCount = computed(() => {
308346})
309347
310348watch (items , (newValue : T []) => {
311- // Clear expanded state for items that no longer exist
312- if (props .expandable ) {
313- const currentKeys = new Set <number | string >()
349+ const currentKeys = new Set <number | string >()
314350
315- newValue .forEach ((item , index ) => {
316- currentKeys .add (getItemKey (item , index ))
317- })
351+ newValue .forEach ((item , index ) => {
352+ currentKeys .add (getItemKey (item , index ))
353+ })
318354
319- // Remove expanded state for items that no longer exist
355+ // Clear expanded state for items that no longer exist
356+ if (props .expandable ) {
320357 expandedState .value .forEach ((_ , key ) => {
321358 if (! currentKeys .has (key )) {
322359 expandedState .value .delete (key )
323360 }
324361 })
325362 }
326363
364+ // Clear selected items that no longer exist
327365 if (props .selectable && props .autoClearSelected ) {
328366 if (props .singleSelect ) {
329- if (! allKeys . value . includes (selected .value as number | string )) {
367+ if (! currentKeys . has (selected .value as number | string )) {
330368 selected .value = undefined
331369 }
332370 } else {
333- if (Array .isArray (selected .value )) {
334- selected .value = selected .value .filter ((k : number | string ) => allKeys . value . includes (k ))
371+ if (Array .isArray (selected .value ) && selected . value . length > 0 ) {
372+ selected .value = selected .value .filter ((k : number | string ) => currentKeys . has (k ))
335373 }
336374 }
337375 }
0 commit comments