@@ -6,7 +6,8 @@ import { type Block, type Fragment, fragmentKey } from './render'
6
6
7
7
interface ForBlock extends Fragment {
8
8
scope : EffectScope
9
- s : [ any , number ] // state, use short key since it's used a lot in generated code
9
+ /** state, use short key since it's used a lot in generated code */
10
+ s : [ item : any , index : number ]
10
11
update : ( ) => void
11
12
key : any
12
13
memo : any [ ] | undefined
@@ -17,7 +18,7 @@ export const createFor = (
17
18
src : ( ) => any [ ] | Record < string , string > | Set < any > | Map < any , any > ,
18
19
renderItem : ( block : ForBlock ) => [ Block , ( ) => void ] ,
19
20
getKey ?: ( item : any , index : number ) => any ,
20
- getMemo ?: ( item : any ) => any [ ] ,
21
+ getMemo ?: ( item : any , index : number ) => any [ ] ,
21
22
hydrationNode ?: Node ,
22
23
) : Fragment => {
23
24
let isMounted = false
@@ -30,89 +31,7 @@ export const createFor = (
30
31
[ fragmentKey ] : true ,
31
32
}
32
33
33
- const mount = (
34
- item : any ,
35
- index : number ,
36
- anchor : Node = parentAnchor ,
37
- ) : ForBlock => {
38
- const scope = effectScope ( )
39
- // TODO support object keys etc.
40
- const block : ForBlock = ( newBlocks [ index ] = {
41
- nodes : null as any ,
42
- update : null as any ,
43
- scope,
44
- s : [ item , index ] ,
45
- key : getKey && getKey ( item , index ) ,
46
- memo : getMemo && getMemo ( item ) ,
47
- [ fragmentKey ] : true ,
48
- } )
49
- const res = scope . run ( ( ) => renderItem ( block ) ) !
50
- block . nodes = res [ 0 ]
51
- block . update = res [ 1 ]
52
- if ( getMemo ) block . update ( )
53
- if ( parent ) insert ( block . nodes , parent , anchor )
54
- return block
55
- }
56
-
57
- const mountList = ( source : any [ ] , offset = 0 ) => {
58
- if ( offset ) source = source . slice ( offset )
59
- for ( let i = 0 , l = source . length ; i < l ; i ++ ) {
60
- mount ( source [ i ] , i + offset )
61
- }
62
- }
63
-
64
- const tryPatchIndex = ( source : any [ ] , i : number ) => {
65
- const block = oldBlocks [ i ]
66
- const item = source [ i ]
67
- if ( block . key === getKey ! ( item , i ) ) {
68
- update ( ( newBlocks [ i ] = block ) , item )
69
- return true
70
- }
71
- }
72
-
73
- const update = getMemo
74
- ? (
75
- block : ForBlock ,
76
- newItem : any ,
77
- oldIndex = block . s [ 1 ] ,
78
- newIndex = oldIndex ,
79
- ) => {
80
- let needsUpdate = newIndex !== oldIndex
81
- if ( ! needsUpdate ) {
82
- const oldMemo = block . memo !
83
- const newMemo = ( block . memo = getMemo ( newItem ) )
84
- for ( let i = 0 ; i < newMemo . length ; i ++ ) {
85
- if ( ( needsUpdate = newMemo [ i ] !== oldMemo [ i ] ) ) {
86
- break
87
- }
88
- }
89
- }
90
- if ( needsUpdate ) {
91
- block . s = [ newItem , newIndex ]
92
- block . update ( )
93
- }
94
- }
95
- : (
96
- block : ForBlock ,
97
- newItem : any ,
98
- oldIndex = block . s [ 1 ] ,
99
- newIndex = oldIndex ,
100
- ) => {
101
- if (
102
- newItem !== block . s [ 0 ] ||
103
- newIndex !== oldIndex ||
104
- ! isReactive ( newItem )
105
- ) {
106
- block . s = [ newItem , newIndex ]
107
- block . update ( )
108
- }
109
- }
110
-
111
- const unmount = ( { nodes, scope } : ForBlock ) => {
112
- remove ( nodes , parent ! )
113
- scope . stop ( )
114
- }
115
-
34
+ const update = getMemo ? updateWithMemo : updateWithoutMemo
116
35
renderEffect ( ( ) => {
117
36
// TODO support more than arrays
118
37
const source = src ( ) as any [ ]
@@ -297,9 +216,92 @@ export const createFor = (
297
216
} )
298
217
299
218
return ref
219
+
220
+ function mount (
221
+ item : any ,
222
+ index : number ,
223
+ anchor : Node = parentAnchor ,
224
+ ) : ForBlock {
225
+ const scope = effectScope ( )
226
+ // TODO support object keys etc.
227
+ const block : ForBlock = ( newBlocks [ index ] = {
228
+ nodes : null ! , // set later
229
+ update : null ! , // set later
230
+ scope,
231
+ s : [ item , index ] ,
232
+ key : getKey && getKey ( item , index ) ,
233
+ memo : getMemo && getMemo ( item , index ) ,
234
+ [ fragmentKey ] : true ,
235
+ } )
236
+ const res = scope . run ( ( ) => renderItem ( block ) ) !
237
+ block . nodes = res [ 0 ]
238
+ block . update = res [ 1 ]
239
+ if ( getMemo ) block . update ( )
240
+ if ( parent ) insert ( block . nodes , parent , anchor )
241
+ return block
242
+ }
243
+
244
+ function mountList ( source : any [ ] , offset = 0 ) {
245
+ if ( offset ) source = source . slice ( offset )
246
+ for ( let i = 0 , l = source . length ; i < l ; i ++ ) {
247
+ mount ( source [ i ] , i + offset )
248
+ }
249
+ }
250
+
251
+ function tryPatchIndex ( source : any [ ] , i : number ) {
252
+ const block = oldBlocks [ i ]
253
+ const item = source [ i ]
254
+ if ( block . key === getKey ! ( item , i ) ) {
255
+ update ( ( newBlocks [ i ] = block ) , item )
256
+ return true
257
+ }
258
+ }
259
+
260
+ function updateWithMemo (
261
+ block : ForBlock ,
262
+ newItem : any ,
263
+ oldIndex = block . s [ 1 ] ,
264
+ newIndex = oldIndex ,
265
+ ) {
266
+ let needsUpdate = newIndex !== oldIndex
267
+ if ( ! needsUpdate ) {
268
+ const oldMemo = block . memo !
269
+ const newMemo = ( block . memo = getMemo ! ( newItem , newIndex ) )
270
+ for ( let i = 0 ; i < newMemo . length ; i ++ ) {
271
+ if ( ( needsUpdate = newMemo [ i ] !== oldMemo [ i ] ) ) {
272
+ break
273
+ }
274
+ }
275
+ }
276
+ if ( needsUpdate ) {
277
+ block . s = [ newItem , newIndex ]
278
+ block . update ( )
279
+ }
280
+ }
281
+
282
+ function updateWithoutMemo (
283
+ block : ForBlock ,
284
+ newItem : any ,
285
+ oldIndex = block . s [ 1 ] ,
286
+ newIndex = oldIndex ,
287
+ ) {
288
+ if (
289
+ newItem !== block . s [ 0 ] ||
290
+ newIndex !== oldIndex ||
291
+ ! isReactive ( newItem )
292
+ ) {
293
+ block . s = [ newItem , newIndex ]
294
+ block . update ( )
295
+ }
296
+ }
297
+
298
+ function unmount ( { nodes, scope } : ForBlock ) {
299
+ remove ( nodes , parent ! )
300
+ scope . stop ( )
301
+ }
300
302
}
301
303
302
- const normalizeAnchor = ( node : Block ) : Node => {
304
+ function normalizeAnchor ( node : Block ) : Node {
303
305
if ( node instanceof Node ) {
304
306
return node
305
307
} else if ( isArray ( node ) ) {
@@ -310,7 +312,7 @@ const normalizeAnchor = (node: Block): Node => {
310
312
}
311
313
312
314
// https://en.wikipedia.org/wiki/Longest_increasing_subsequence
313
- const getSequence = ( arr : number [ ] ) : number [ ] => {
315
+ function getSequence ( arr : number [ ] ) : number [ ] {
314
316
const p = arr . slice ( )
315
317
const result = [ 0 ]
316
318
let i , j , u , v , c
0 commit comments