context: CodegenContext,
): CodeFragment[] {
const { vaporHelper } = context
- const { source, value, key, index, render, keyProp, once, id, memo } = oper
+ const {
+ source,
+ value,
+ key,
+ index,
+ render,
+ keyProp,
+ once,
+ id,
+ memo,
+ container,
+ } = oper
let isDestructureAssignment = false
let rawValue: string | null = null
blockFn,
genCallback(keyProp),
genCallback(memo),
+ container != null && `n${container}`,
false, // todo: hydrationNode
once && 'true',
),
return (): void => {
exitBlock()
+ const { parent } = context
+ let container: number | undefined
+ if (
+ parent &&
+ parent.block.node !== parent.node &&
+ parent.node.children.length === 1
+ ) {
+ container = parent.reference()
+ }
context.registerOperation({
type: IRNodeTypes.FOR,
id,
render,
once: context.inVOnce,
memo: memo && memo.exp,
+ container,
})
}
}
renderItem: (block: ForBlock['state']) => Block,
getKey?: (item: any, key: any, index?: number) => any,
getMemo?: (item: any, key: any, index?: number) => any[],
+ container?: ParentNode,
hydrationNode?: Node,
once?: boolean,
): Fragment => {
let oldBlocks: ForBlock[] = []
let newBlocks: ForBlock[]
let parent: ParentNode | undefined | null
- const parentAnchor = __DEV__ ? createComment('for') : createTextNode()
+ const parentAnchor = container
+ ? undefined
+ : __DEV__
+ ? createComment('for')
+ : createTextNode()
const ref: Fragment = {
nodes: oldBlocks,
[fragmentKey]: true,
isMounted = true
mountList(source)
} else {
- parent = parent || parentAnchor.parentNode
+ parent = parent || container || parentAnchor!.parentNode
if (!oldLength) {
// fast path for all new
mountList(source)
} else if (!newLength) {
- // fast path for clearing
- for (let i = 0; i < oldLength; i++) {
- unmount(oldBlocks[i])
+ // fast path for all removed
+ if (container) {
+ container.textContent = ''
+ for (let i = 0; i < oldLength; i++) {
+ oldBlocks[i].scope.stop()
+ }
+ } else {
+ // fast path for clearing
+ for (let i = 0; i < oldLength; i++) {
+ unmount(oldBlocks[i])
+ }
}
} else if (!getKey) {
// unkeyed fast path
}
}
- ref.nodes = [(oldBlocks = newBlocks), parentAnchor]
+ ref.nodes = [(oldBlocks = newBlocks)]
+ if (parentAnchor) {
+ ref.nodes.push(parentAnchor)
+ }
}
function mount(
source: any,
idx: number,
- anchor: Node = parentAnchor,
+ anchor: Node | undefined = parentAnchor,
): ForBlock {
const scope = effectScope()