diff --git a/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap b/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap
index 430aa254e52..32a6fd611ee 100644
--- a/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap
+++ b/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap
@@ -319,15 +319,18 @@ return function render(_ctx, _cache) {
}"
`;
-exports[`compiler: hoistStatic transform should NOT hoist element with dynamic props 1`] = `
+exports[`compiler: hoistStatic transform should NOT hoist element with dynamic props (but hoist the props list) 1`] = `
"const _Vue = Vue
+const { createElementVNode: _createElementVNode } = _Vue
+
+const _hoisted_1 = [\\"id\\"]
return function render(_ctx, _cache) {
with (_ctx) {
const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
return (_openBlock(), _createElementBlock(\\"div\\", null, [
- _createElementVNode(\\"div\\", { id: foo }, null, 8 /* PROPS */, [\\"id\\"])
+ _createElementVNode(\\"div\\", { id: foo }, null, 8 /* PROPS */, _hoisted_1)
]))
}
}"
diff --git a/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts b/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts
index a91635ed687..b2e125afdf5 100644
--- a/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts
+++ b/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts
@@ -186,9 +186,9 @@ describe('compiler: hoistStatic transform', () => {
expect(generate(root).code).toMatchSnapshot()
})
- test('should NOT hoist element with dynamic props', () => {
+ test('should NOT hoist element with dynamic props (but hoist the props list)', () => {
const root = transformWithHoist(`
`)
- expect(root.hoists.length).toBe(0)
+ expect(root.hoists.length).toBe(1)
expect((root.codegenNode as VNodeCall).children).toMatchObject([
{
type: NodeTypes.ELEMENT,
@@ -200,7 +200,11 @@ describe('compiler: hoistStatic transform', () => {
}),
children: undefined,
patchFlag: genFlagText(PatchFlags.PROPS),
- dynamicProps: `["id"]`
+ dynamicProps: {
+ type: NodeTypes.SIMPLE_EXPRESSION,
+ content: `_hoisted_1`,
+ isStatic: false
+ }
}
}
])
diff --git a/packages/compiler-core/src/ast.ts b/packages/compiler-core/src/ast.ts
index b5f933ea59a..2cec62d732d 100644
--- a/packages/compiler-core/src/ast.ts
+++ b/packages/compiler-core/src/ast.ts
@@ -288,7 +288,7 @@ export interface VNodeCall extends Node {
| ForRenderListExpression // v-for fragment call
| undefined
patchFlag: string | undefined
- dynamicProps: string | undefined
+ dynamicProps: string | SimpleExpressionNode | undefined
directives: DirectiveArguments | undefined
isBlock: boolean
disableTracking: boolean
diff --git a/packages/compiler-core/src/transform.ts b/packages/compiler-core/src/transform.ts
index e2329b039b1..bc03d35135f 100644
--- a/packages/compiler-core/src/transform.ts
+++ b/packages/compiler-core/src/transform.ts
@@ -113,7 +113,7 @@ export interface TransformContext
onNodeRemoved(): void
addIdentifiers(exp: ExpressionNode | string): void
removeIdentifiers(exp: ExpressionNode | string): void
- hoist(exp: JSChildNode): SimpleExpressionNode
+ hoist(exp: string | JSChildNode): SimpleExpressionNode
cache(exp: T, isVNode?: boolean): CacheExpression | T
constantCache: Map
@@ -277,6 +277,7 @@ export function createTransformContext(
}
},
hoist(exp) {
+ if (isString(exp)) exp = createSimpleExpression(exp, false)
context.hoists.push(exp)
const identifier = createSimpleExpression(
`_hoisted_${context.hoists.length}`,
diff --git a/packages/compiler-core/src/transforms/hoistStatic.ts b/packages/compiler-core/src/transforms/hoistStatic.ts
index aad6d879413..ee18b550fc8 100644
--- a/packages/compiler-core/src/transforms/hoistStatic.ts
+++ b/packages/compiler-core/src/transforms/hoistStatic.ts
@@ -102,6 +102,9 @@ function walk(
codegenNode.props = context.hoist(props)
}
}
+ if (codegenNode.dynamicProps) {
+ codegenNode.dynamicProps = context.hoist(codegenNode.dynamicProps)
+ }
}
}
} else if (child.type === NodeTypes.TEXT_CALL) {