mirror of https://github.com/vuejs/core.git
refactor(vapor): use bitwise flags for v-for runtime optimizations
This commit is contained in:
parent
63cf2ee3f1
commit
242cc15fa6
|
@ -23,7 +23,7 @@ export function render(_ctx) {
|
||||||
const n2 = t0()
|
const n2 = t0()
|
||||||
_setTemplateRef(n2, "foo", void 0, true)
|
_setTemplateRef(n2, "foo", void 0, true)
|
||||||
return n2
|
return n2
|
||||||
}, null, null, true)
|
}, null, 4)
|
||||||
return n0
|
return n0
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -77,7 +77,7 @@ export function render(_ctx) {
|
||||||
const x4 = _child(n4)
|
const x4 = _child(n4)
|
||||||
_renderEffect(() => _setText(x4, _toDisplayString(_for_item1.value+_for_item0.value)))
|
_renderEffect(() => _setText(x4, _toDisplayString(_for_item1.value+_for_item0.value)))
|
||||||
return n4
|
return n4
|
||||||
}, null, null, null, true)
|
}, null, 1)
|
||||||
_insert(n2, n5)
|
_insert(n2, n5)
|
||||||
return n5
|
return n5
|
||||||
})
|
})
|
||||||
|
|
|
@ -68,7 +68,7 @@ export function render(_ctx) {
|
||||||
const n0 = _createFor(() => (_ctx.list), (_for_item0) => {
|
const n0 = _createFor(() => (_ctx.list), (_for_item0) => {
|
||||||
const n2 = t0()
|
const n2 = t0()
|
||||||
return n2
|
return n2
|
||||||
}, null, null, true)
|
}, null, 4)
|
||||||
return n0
|
return n0
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -10,6 +10,7 @@ import type { ForIRNode } from '../ir'
|
||||||
import { type CodeFragment, NEWLINE, genCall, genMulti } from './utils'
|
import { type CodeFragment, NEWLINE, genCall, genMulti } from './utils'
|
||||||
import type { Identifier } from '@babel/types'
|
import type { Identifier } from '@babel/types'
|
||||||
import { parseExpression } from '@babel/parser'
|
import { parseExpression } from '@babel/parser'
|
||||||
|
import { VaporVForFlags } from '../../../shared/src/vaporFlags'
|
||||||
|
|
||||||
export function genFor(
|
export function genFor(
|
||||||
oper: ForIRNode,
|
oper: ForIRNode,
|
||||||
|
@ -80,6 +81,17 @@ export function genFor(
|
||||||
const blockFn = context.withId(() => genBlock(render, context, args), idMap)
|
const blockFn = context.withId(() => genBlock(render, context, args), idMap)
|
||||||
exitScope()
|
exitScope()
|
||||||
|
|
||||||
|
let flags = 0
|
||||||
|
if (onlyChild) {
|
||||||
|
flags |= VaporVForFlags.FAST_REMOVE
|
||||||
|
}
|
||||||
|
if (component) {
|
||||||
|
flags |= VaporVForFlags.IS_COMPONENT
|
||||||
|
}
|
||||||
|
if (once) {
|
||||||
|
flags |= VaporVForFlags.ONCE
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
NEWLINE,
|
NEWLINE,
|
||||||
`const n${id} = `,
|
`const n${id} = `,
|
||||||
|
@ -88,9 +100,7 @@ export function genFor(
|
||||||
sourceExpr,
|
sourceExpr,
|
||||||
blockFn,
|
blockFn,
|
||||||
genCallback(keyProp),
|
genCallback(keyProp),
|
||||||
component && 'true',
|
flags ? String(flags) : undefined,
|
||||||
once && 'true',
|
|
||||||
onlyChild && `true`,
|
|
||||||
// todo: hydrationNode
|
// todo: hydrationNode
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { warn } from '@vue/runtime-dom'
|
||||||
import { currentInstance, isVaporComponent } from './component'
|
import { currentInstance, isVaporComponent } from './component'
|
||||||
import type { DynamicSlot } from './componentSlots'
|
import type { DynamicSlot } from './componentSlots'
|
||||||
import { renderEffect } from './renderEffect'
|
import { renderEffect } from './renderEffect'
|
||||||
|
import { VaporVForFlags } from '../../shared/src/vaporFlags'
|
||||||
|
|
||||||
class ForBlock extends VaporFragment {
|
class ForBlock extends VaporFragment {
|
||||||
scope: EffectScope | undefined
|
scope: EffectScope | undefined
|
||||||
|
@ -64,13 +65,7 @@ export const createFor = (
|
||||||
index: ShallowRef<number | undefined>,
|
index: ShallowRef<number | undefined>,
|
||||||
) => Block,
|
) => Block,
|
||||||
getKey?: (item: any, key: any, index?: number) => any,
|
getKey?: (item: any, key: any, index?: number) => any,
|
||||||
/**
|
flags = 0,
|
||||||
* Whether this v-for is used directly on a component. If true, we can avoid
|
|
||||||
* creating an extra fragment / scope for each block
|
|
||||||
*/
|
|
||||||
isComponent = false,
|
|
||||||
once?: boolean,
|
|
||||||
canUseFastRemove?: boolean,
|
|
||||||
// hydrationNode?: Node,
|
// hydrationNode?: Node,
|
||||||
): VaporFragment => {
|
): VaporFragment => {
|
||||||
let isMounted = false
|
let isMounted = false
|
||||||
|
@ -80,6 +75,8 @@ export const createFor = (
|
||||||
const parentAnchor = __DEV__ ? createComment('for') : createTextNode()
|
const parentAnchor = __DEV__ ? createComment('for') : createTextNode()
|
||||||
const frag = new VaporFragment(oldBlocks)
|
const frag = new VaporFragment(oldBlocks)
|
||||||
const instance = currentInstance!
|
const instance = currentInstance!
|
||||||
|
const canUseFastRemove = flags & VaporVForFlags.FAST_REMOVE
|
||||||
|
const isComponent = flags & VaporVForFlags.IS_COMPONENT
|
||||||
|
|
||||||
if (__DEV__ && !instance) {
|
if (__DEV__ && !instance) {
|
||||||
warn('createFor() can only be used inside setup()')
|
warn('createFor() can only be used inside setup()')
|
||||||
|
@ -354,7 +351,11 @@ export const createFor = (
|
||||||
doRemove && removeBlock(nodes, parent!)
|
doRemove && removeBlock(nodes, parent!)
|
||||||
}
|
}
|
||||||
|
|
||||||
once ? renderList() : renderEffect(renderList)
|
if (flags & VaporVForFlags.ONCE) {
|
||||||
|
renderList()
|
||||||
|
} else {
|
||||||
|
renderEffect(renderList)
|
||||||
|
}
|
||||||
return frag
|
return frag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
/**
|
||||||
|
* Flags to optimize vapor `createFor` runtime behavior, shared between the
|
||||||
|
* compiler and the runtime
|
||||||
|
*/
|
||||||
|
export enum VaporVForFlags {
|
||||||
|
/**
|
||||||
|
* v-for is the only child of a parent container, so it can take the fast
|
||||||
|
* path with textContent = '' when the whole list is emptied
|
||||||
|
*/
|
||||||
|
FAST_REMOVE = 1,
|
||||||
|
/**
|
||||||
|
* v-for used on component - we can skip creating child scopes for each block
|
||||||
|
* because the component itself already has a scope.
|
||||||
|
*/
|
||||||
|
IS_COMPONENT = 1 << 1,
|
||||||
|
/**
|
||||||
|
* v-for inside v-ince
|
||||||
|
*/
|
||||||
|
ONCE = 1 << 2,
|
||||||
|
}
|
Loading…
Reference in New Issue