1
1
<script setup lang="ts" vapor>
2
- import { ref , shallowRef } from ' @vue/vapor'
2
+ import {
3
+ ref ,
4
+ shallowRef ,
5
+ triggerRef ,
6
+ watch ,
7
+ type ShallowRef ,
8
+ type WatchSource ,
9
+ } from ' @vue/vapor'
3
10
import { buildData } from ' ./data'
4
11
import { defer , wrap } from ' ./profiling'
5
12
@@ -9,50 +16,47 @@ const selected = ref<number>()
9
16
const rows = shallowRef <
10
17
{
11
18
id : number
12
- label : string
19
+ label : ShallowRef < string >
13
20
}[]
14
21
> ([])
15
22
16
- function setRows(update = rows .value .slice ()) {
17
- rows .value = update
18
- }
19
-
23
+ // Bench Add: https://jsbench.me/45lzxprzmu/1
20
24
const add = wrap (' add' , () => {
21
- rows .value = rows .value .concat (buildData (1000 ))
25
+ rows .value .push (... buildData (1000 ))
26
+ triggerRef (rows )
22
27
})
23
28
24
29
const remove = wrap (' remove' , (id : number ) => {
25
30
rows .value .splice (
26
31
rows .value .findIndex (d => d .id === id ),
27
32
1 ,
28
33
)
29
- setRows ( )
34
+ triggerRef ( rows )
30
35
})
31
36
32
37
const select = wrap (' select' , (id : number ) => {
33
38
selected .value = id
34
39
})
35
40
36
41
const run = wrap (' run' , () => {
37
- setRows ( buildData () )
42
+ rows . value = buildData ()
38
43
selected .value = undefined
39
44
})
40
45
41
46
const update = wrap (' update' , () => {
42
47
const _rows = rows .value
43
- for (let i = 0 ; i < _rows .length ; i += 10 ) {
44
- _rows [i ].label += ' !!!'
48
+ for (let i = 0 , len = _rows .length ; i < len ; i += 10 ) {
49
+ _rows [i ].label . value += ' !!!'
45
50
}
46
- setRows ()
47
51
})
48
52
49
53
const runLots = wrap (' runLots' , () => {
50
- setRows ( buildData (10000 ) )
54
+ rows . value = buildData (10000 )
51
55
selected .value = undefined
52
56
})
53
57
54
58
const clear = wrap (' clear' , () => {
55
- setRows ([])
59
+ rows . value = []
56
60
selected .value = undefined
57
61
})
58
62
@@ -63,7 +67,7 @@ const swapRows = wrap('swap', () => {
63
67
const d998 = _rows [998 ]
64
68
_rows [1 ] = d998
65
69
_rows [998 ] = d1
66
- setRows ( )
70
+ triggerRef ( rows )
67
71
}
68
72
})
69
73
@@ -74,6 +78,18 @@ async function bench() {
74
78
await runLots ()
75
79
}
76
80
}
81
+
82
+ // Reduce the complexity of `selected` from O(n) to O(1).
83
+ function createSelector(source : WatchSource ) {
84
+ const cache: Record <keyof any , ShallowRef <boolean >> = {}
85
+ watch (source , (val , old ) => {
86
+ if (old != undefined ) cache [old ]! .value = false
87
+ if (val != undefined ) cache [val ]! .value = true
88
+ })
89
+ return (id : keyof any ) => (cache [id ] ?? = shallowRef (false )).value
90
+ }
91
+
92
+ const isSelected = createSelector (selected )
77
93
</script >
78
94
79
95
<template >
@@ -96,11 +112,11 @@ async function bench() {
96
112
<tr
97
113
v-for =" row of rows"
98
114
:key =" row.id"
99
- :class =" { danger: row.id === selected }"
115
+ :class =" { danger: isSelected( row.id) }"
100
116
>
101
117
<td >{{ row.id }}</td >
102
118
<td >
103
- <a @click =" select(row.id)" >{{ row.label }}</a >
119
+ <a @click =" select(row.id)" >{{ row.label.value }}</a >
104
120
</td >
105
121
<td >
106
122
<button @click =" remove(row.id)" >x</button >
0 commit comments