Skip to content

Commit 11bcb21

Browse files
committed
wip: handle keyed element transition
1 parent 7e593c2 commit 11bcb21

File tree

7 files changed

+65
-12
lines changed

7 files changed

+65
-12
lines changed

packages/compiler-vapor/src/generators/block.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type { CodegenContext } from '../generate'
1313
import { genEffects, genOperations } from './operation'
1414
import { genChildren } from './template'
1515
import { toValidAssetId } from '@vue/compiler-dom'
16+
import { genExpression } from './expression'
1617

1718
export function genBlock(
1819
oper: BlockIRNode,
@@ -40,7 +41,7 @@ export function genBlockContent(
4041
customReturns?: (returns: CodeFragment[]) => CodeFragment[],
4142
): CodeFragment[] {
4243
const [frag, push] = buildCodeFragment()
43-
const { dynamic, effect, operation, returns } = block
44+
const { dynamic, effect, operation, returns, key } = block
4445
const resetBlock = context.enterBlock(block)
4546

4647
if (root) {
@@ -57,7 +58,10 @@ export function genBlockContent(
5758

5859
if (dynamic.needsKey) {
5960
for (const child of dynamic.children) {
60-
push(NEWLINE, `n${child.id}.key = ${JSON.stringify(child.id)}`)
61+
const keyValue = key
62+
? genExpression(key, context)
63+
: JSON.stringify(child.id)
64+
push(NEWLINE, `n${child.id}.key = `, ...keyValue)
6165
}
6266
}
6367

packages/compiler-vapor/src/generators/component.ts

+20-3
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ export function genCreateComponent(
9999
return `_${builtInTag}`
100100
}
101101
return genExpression(
102-
extend(createSimpleExpression(operation.tag, false), { ast: null }),
102+
extend(createSimpleExpression(tag, false), { ast: null }),
103103
context,
104104
)
105105
}
@@ -402,7 +402,7 @@ function genSlotBlockWithProps(oper: SlotBlockIRNode, context: CodegenContext) {
402402
let propsName: string | undefined
403403
let exitScope: (() => void) | undefined
404404
let depth: number | undefined
405-
const { props } = oper
405+
const { props, key } = oper
406406
const idsOfProps = new Set<string>()
407407

408408
if (props) {
@@ -430,11 +430,28 @@ function genSlotBlockWithProps(oper: SlotBlockIRNode, context: CodegenContext) {
430430
? `${propsName}[${JSON.stringify(id)}]`
431431
: null),
432432
)
433-
const blockFn = context.withId(
433+
let blockFn = context.withId(
434434
() => genBlock(oper, context, [propsName]),
435435
idMap,
436436
)
437437
exitScope && exitScope()
438438

439+
if (key) {
440+
blockFn = [
441+
`() => {`,
442+
INDENT_START,
443+
NEWLINE,
444+
`return `,
445+
...genCall(
446+
context.helper('createKeyedFragment'),
447+
[`() => `, ...genExpression(key, context)],
448+
blockFn,
449+
),
450+
INDENT_END,
451+
NEWLINE,
452+
`}`,
453+
]
454+
}
455+
439456
return blockFn
440457
}

packages/compiler-vapor/src/ir/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export enum IRNodeTypes {
4040

4141
export interface BaseIRNode {
4242
type: IRNodeTypes
43+
key?: SimpleExpressionNode | undefined
4344
}
4445

4546
export type CoreHelper = keyof typeof import('packages/runtime-dom/src')

packages/compiler-vapor/src/transforms/vIf.ts

+10-5
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,16 @@ export function createIfBranch(
130130
return [branch, exitBlock]
131131
}
132132

133-
function isInTransition(context: TransformContext<ElementNode>): boolean {
133+
export function isInTransition(
134+
context: TransformContext<ElementNode>,
135+
): boolean {
134136
const parentNode = context.parent && context.parent.node
135-
return !!(
136-
parentNode &&
137-
parentNode.type === NodeTypes.ELEMENT &&
138-
(parentNode.tag === 'transition' || parentNode.tag === 'Transition')
137+
return !!(parentNode && isTransitionNode(parentNode as ElementNode))
138+
}
139+
140+
export function isTransitionNode(node: ElementNode): boolean {
141+
return (
142+
node.type === NodeTypes.ELEMENT &&
143+
(node.tag === 'transition' || node.tag === 'Transition')
139144
)
140145
}

packages/compiler-vapor/src/transforms/vSlot.ts

+17-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ import {
2323
type SlotBlockIRNode,
2424
type VaporDirectiveNode,
2525
} from '../ir'
26-
import { findDir, resolveExpression } from '../utils'
26+
import { findDir, findProp, resolveExpression } from '../utils'
27+
import { isTransitionNode } from './vIf'
2728

2829
export const transformVSlot: NodeTransform = (node, context) => {
2930
if (node.type !== NodeTypes.ELEMENT) return
@@ -72,7 +73,18 @@ function transformComponentSlot(
7273
!(n.type === NodeTypes.ELEMENT && n.props.some(isVSlot)),
7374
)
7475

75-
const [block, onExit] = createSlotBlock(node, dir, context)
76+
let slotKey
77+
if (isTransitionNode(node)) {
78+
const keyProp = findProp(
79+
nonSlotTemplateChildren[0] as ElementNode,
80+
'key',
81+
) as VaporDirectiveNode
82+
if (keyProp) {
83+
slotKey = keyProp.exp
84+
}
85+
}
86+
87+
const [block, onExit] = createSlotBlock(node, dir, context, slotKey)
7688

7789
const { slots } = context
7890

@@ -233,9 +245,12 @@ function createSlotBlock(
233245
slotNode: ElementNode,
234246
dir: VaporDirectiveNode | undefined,
235247
context: TransformContext<ElementNode>,
248+
key: SimpleExpressionNode | undefined = undefined,
236249
): [SlotBlockIRNode, () => void] {
237250
const block: SlotBlockIRNode = newBlock(slotNode)
238251
block.props = dir && dir.exp
252+
block.key = key
253+
if (key) block.dynamic.needsKey = true
239254
const exitBlock = context.enterBlock(block)
240255
return [block, exitBlock]
241256
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { type Block, type BlockFn, DynamicFragment } from './block'
2+
import { renderEffect } from './renderEffect'
3+
4+
export function createKeyedFragment(key: () => any, render: BlockFn): Block {
5+
const frag = __DEV__ ? new DynamicFragment('keyed') : new DynamicFragment()
6+
renderEffect(() => {
7+
frag.update(render, key())
8+
})
9+
return frag
10+
}

packages/runtime-vapor/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export {
2424
} from './dom/prop'
2525
export { on, delegate, delegateEvents, setDynamicEvents } from './dom/event'
2626
export { createIf } from './apiCreateIf'
27+
export { createKeyedFragment } from './apiCreateFragment'
2728
export {
2829
createFor,
2930
createForSlots,

0 commit comments

Comments
 (0)