Skip to content

Commit d51d558

Browse files
committed
refactor(runtime-vapor): tweak createFor
1 parent 83641f7 commit d51d558

File tree

1 file changed

+89
-87
lines changed
  • packages/runtime-vapor/src

1 file changed

+89
-87
lines changed

packages/runtime-vapor/src/for.ts

+89-87
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import { type Block, type Fragment, fragmentKey } from './render'
66

77
interface ForBlock extends Fragment {
88
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]
1011
update: () => void
1112
key: any
1213
memo: any[] | undefined
@@ -17,7 +18,7 @@ export const createFor = (
1718
src: () => any[] | Record<string, string> | Set<any> | Map<any, any>,
1819
renderItem: (block: ForBlock) => [Block, () => void],
1920
getKey?: (item: any, index: number) => any,
20-
getMemo?: (item: any) => any[],
21+
getMemo?: (item: any, index: number) => any[],
2122
hydrationNode?: Node,
2223
): Fragment => {
2324
let isMounted = false
@@ -30,89 +31,7 @@ export const createFor = (
3031
[fragmentKey]: true,
3132
}
3233

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
11635
renderEffect(() => {
11736
// TODO support more than arrays
11837
const source = src() as any[]
@@ -297,9 +216,92 @@ export const createFor = (
297216
})
298217

299218
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+
}
300302
}
301303

302-
const normalizeAnchor = (node: Block): Node => {
304+
function normalizeAnchor(node: Block): Node {
303305
if (node instanceof Node) {
304306
return node
305307
} else if (isArray(node)) {
@@ -310,7 +312,7 @@ const normalizeAnchor = (node: Block): Node => {
310312
}
311313

312314
// https://en.wikipedia.org/wiki/Longest_increasing_subsequence
313-
const getSequence = (arr: number[]): number[] => {
315+
function getSequence(arr: number[]): number[] {
314316
const p = arr.slice()
315317
const result = [0]
316318
let i, j, u, v, c

0 commit comments

Comments
 (0)