Skip to content

Commit 6a8690a

Browse files
author
Gilmar Custódio de Sales
committed
perf(ui): rewriting the inner strategies of q-tree to use hashes instead of greedy iterations
1 parent 4ebebf0 commit 6a8690a

File tree

1 file changed

+45
-61
lines changed

1 file changed

+45
-61
lines changed

ui/src/components/tree/QTree.js

Lines changed: 45 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,9 @@ export default createComponent({
9090
const isDark = useDark(props, $q)
9191

9292
const lazy = ref({})
93-
const innerTicked = ref(props.ticked || [])
94-
const innerExpanded = ref(props.expanded || [])
93+
const innerTicked = ref(new Set(props.ticked || []))
94+
const innerExpanded = ref(new Set(props.expanded || []))
95+
const innerNodes = ref(new Map(getNodesPairs(props.nodes)))
9596

9697
let blurTargets = {}
9798

@@ -139,7 +140,7 @@ export default createComponent({
139140
const travel = (node, parent) => {
140141
const tickStrategy = node.tickStrategy || (parent ? parent.tickStrategy : props.tickStrategy)
141142
const
142-
key = node[ props.nodeKey ],
143+
key = getNodeKey(node),
143144
isParent = node[ props.childrenKey ] && Array.isArray(node[ props.childrenKey ]) && node[ props.childrenKey ].length !== 0,
144145
selectable = node.disabled !== true && hasSelection.value === true && node.selectable !== false,
145146
expandable = node.disabled !== true && node.expandable !== false,
@@ -174,7 +175,7 @@ export default createComponent({
174175

175176
selected: key === props.selected && selectable === true,
176177
selectable,
177-
expanded: isParent === true ? innerExpanded.value.includes(key) : false,
178+
expanded: isParent === true ? innerExpanded.value.has(key) : false,
178179
expandable,
179180
noTick: node.noTick === true || (strictTicking !== true && localLazy && localLazy !== 'loaded'),
180181
tickable,
@@ -184,8 +185,8 @@ export default createComponent({
184185
leafFilteredTicking,
185186
leafTicking,
186187
ticked: strictTicking === true
187-
? innerTicked.value.includes(key)
188-
: (isParent === true ? false : innerTicked.value.includes(key))
188+
? innerTicked.value.has(key)
189+
: (isParent === true ? false : innerTicked.value.has(key))
189190
}
190191

191192
meta[ key ] = m
@@ -246,32 +247,39 @@ export default createComponent({
246247
})
247248

248249
watch(() => props.ticked, val => {
249-
innerTicked.value = val
250+
innerTicked.value = new Set(val)
250251
})
251252

252253
watch(() => props.expanded, val => {
253-
innerExpanded.value = val
254+
innerExpanded.value = new Set(val)
254255
})
255256

256-
function getNodeByKey (key) {
257-
const reduce = [].reduce
257+
watch(() => props.nodes, val => {
258+
innerNodes.value = new Map(getNodesPairs(val))
259+
})
258260

259-
const find = (result, node) => {
260-
if (result || !node) {
261-
return result
262-
}
263-
if (Array.isArray(node) === true) {
264-
return reduce.call(Object(node), find, result)
265-
}
266-
if (node[ props.nodeKey ] === key) {
267-
return node
268-
}
269-
if (node[ props.childrenKey ]) {
270-
return find(null, node[ props.childrenKey ])
261+
function getNodesPairs (nodes) {
262+
const nodePairs = []
263+
264+
const travel = (node) => {
265+
if (Array.isArray(node[ props.childrenKey ])) {
266+
node[ props.childrenKey ].forEach(travel)
271267
}
268+
269+
nodePairs.push([ getNodeKey(node), node ])
272270
}
273271

274-
return find(null, props.nodes)
272+
nodes.forEach(travel)
273+
274+
return nodePairs
275+
}
276+
277+
function getNodeKey (node) {
278+
return node[ props.nodeKey ]
279+
}
280+
281+
function getNodeByKey (key) {
282+
return innerNodes.value.get(key) ?? null
275283
}
276284

277285
function getTickedNodes () {
@@ -293,28 +301,20 @@ export default createComponent({
293301
emit('update:expanded', [])
294302
}
295303
else {
296-
innerExpanded.value = []
304+
innerExpanded.value = new Set([])
297305
}
298306
}
299307

300308
function expandAll () {
301-
const expanded = []
302-
const travel = node => {
303-
if (node[ props.childrenKey ] && node[ props.childrenKey ].length !== 0) {
304-
if (node.expandable !== false && node.disabled !== true) {
305-
expanded.push(node[ props.nodeKey ])
306-
node[ props.childrenKey ].forEach(travel)
307-
}
308-
}
309-
}
309+
const expanded = [ ...innerNodes.value.keys() ]
310310

311-
props.nodes.forEach(travel)
311+
const shouldEmit = props.expanded !== void 0
312312

313-
if (props.expanded !== void 0) {
313+
if (shouldEmit) {
314314
emit('update:expanded', expanded)
315315
}
316316
else {
317-
innerExpanded.value = expanded
317+
innerExpanded.value = new Set(expanded)
318318
}
319319
}
320320

@@ -353,13 +353,8 @@ export default createComponent({
353353
}
354354

355355
function localSetExpanded (key, state) {
356-
let target = innerExpanded.value
357356
const shouldEmit = props.expanded !== void 0
358357

359-
if (shouldEmit === true) {
360-
target = target.slice()
361-
}
362-
363358
if (state) {
364359
if (props.accordion) {
365360
if (meta.value[ key ]) {
@@ -373,30 +368,25 @@ export default createComponent({
373368
}
374369
else {
375370
props.nodes.forEach(node => {
376-
const k = node[ props.nodeKey ]
371+
const k = getNodeKey(node)
377372
if (k !== key) {
378373
collapse.push(k)
379374
}
380375
})
381376
}
382377
if (collapse.length !== 0) {
383-
target = target.filter(k => collapse.includes(k) === false)
378+
collapse.forEach(key => innerExpanded.value.delete(key))
384379
}
385380
}
386381
}
387-
388-
target = target.concat([ key ])
389-
.filter((key, index, self) => self.indexOf(key) === index)
382+
innerExpanded.value.add(key)
390383
}
391384
else {
392-
target = target.filter(k => k !== key)
385+
innerExpanded.value.delete(key)
393386
}
394387

395388
if (shouldEmit === true) {
396-
emit('update:expanded', target)
397-
}
398-
else {
399-
innerExpanded.value = target
389+
emit('update:expanded', [ ...innerExpanded.value ])
400390
}
401391
}
402392

@@ -407,23 +397,17 @@ export default createComponent({
407397
}
408398

409399
function setTicked (keys, state) {
410-
let target = innerTicked.value
411400
const shouldEmit = props.ticked !== void 0
412401

413-
if (shouldEmit === true) {
414-
target = target.slice()
415-
}
416-
417402
if (state) {
418-
target = target.concat(keys)
419-
.filter((key, index, self) => self.indexOf(key) === index)
403+
keys.forEach(key => innerTicked.value.add(key))
420404
}
421405
else {
422-
target = target.filter(k => keys.includes(k) === false)
406+
keys.forEach(key => innerTicked.value.delete(key))
423407
}
424408

425409
if (shouldEmit === true) {
426-
emit('update:ticked', target)
410+
emit('update:ticked', [ ...innerTicked.value ])
427411
}
428412
}
429413

@@ -482,7 +466,7 @@ export default createComponent({
482466

483467
function getNode (node) {
484468
const
485-
key = node[ props.nodeKey ],
469+
key = getNodeKey(node),
486470
m = meta.value[ key ],
487471
header = node.header
488472
? slots[ `header-${ node.header }` ] || slots[ 'default-header' ]

0 commit comments

Comments
 (0)