import { type CodeFragment, NEWLINE, genCall, genMulti } from './utils'
import type { Identifier } from '@babel/types'
import { parseExpression } from '@babel/parser'
+import { VaporVForFlags } from '../../../shared/src/vaporFlags'
export function genFor(
oper: ForIRNode,
const blockFn = context.withId(() => genBlock(render, context, args), idMap)
exitScope()
+ let flags = 0
+ if (onlyChild) {
+ flags |= VaporVForFlags.FAST_REMOVE
+ }
+ if (component) {
+ flags |= VaporVForFlags.IS_COMPONENT
+ }
+ if (once) {
+ flags |= VaporVForFlags.ONCE
+ }
+
return [
NEWLINE,
`const n${id} = `,
sourceExpr,
blockFn,
genCallback(keyProp),
- component && 'true',
- once && 'true',
- onlyChild && `true`,
+ flags ? String(flags) : undefined,
// todo: hydrationNode
),
]
import { currentInstance, isVaporComponent } from './component'
import type { DynamicSlot } from './componentSlots'
import { renderEffect } from './renderEffect'
+import { VaporVForFlags } from '../../shared/src/vaporFlags'
class ForBlock extends VaporFragment {
scope: EffectScope | undefined
index: ShallowRef<number | undefined>,
) => Block,
getKey?: (item: any, key: any, index?: number) => any,
- /**
- * 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,
+ flags = 0,
// hydrationNode?: Node,
): VaporFragment => {
let isMounted = false
const parentAnchor = __DEV__ ? createComment('for') : createTextNode()
const frag = new VaporFragment(oldBlocks)
const instance = currentInstance!
+ const canUseFastRemove = flags & VaporVForFlags.FAST_REMOVE
+ const isComponent = flags & VaporVForFlags.IS_COMPONENT
if (__DEV__ && !instance) {
warn('createFor() can only be used inside setup()')
doRemove && removeBlock(nodes, parent!)
}
- once ? renderList() : renderEffect(renderList)
+ if (flags & VaporVForFlags.ONCE) {
+ renderList()
+ } else {
+ renderEffect(renderList)
+ }
return frag
}
--- /dev/null
+/**
+ * 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,
+}