perf: hoist dynamic props lists

This commit is contained in:
Evan You 2021-07-07 14:47:59 -04:00
parent 979a841946
commit 02339b67d8
5 changed files with 18 additions and 7 deletions

View File

@ -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 _Vue = Vue
const { createElementVNode: _createElementVNode } = _Vue
const _hoisted_1 = [\\"id\\"]
return function render(_ctx, _cache) { return function render(_ctx, _cache) {
with (_ctx) { with (_ctx) {
const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
return (_openBlock(), _createElementBlock(\\"div\\", null, [ return (_openBlock(), _createElementBlock(\\"div\\", null, [
_createElementVNode(\\"div\\", { id: foo }, null, 8 /* PROPS */, [\\"id\\"]) _createElementVNode(\\"div\\", { id: foo }, null, 8 /* PROPS */, _hoisted_1)
])) ]))
} }
}" }"

View File

@ -186,9 +186,9 @@ describe('compiler: hoistStatic transform', () => {
expect(generate(root).code).toMatchSnapshot() 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(`<div><div :id="foo"/></div>`) const root = transformWithHoist(`<div><div :id="foo"/></div>`)
expect(root.hoists.length).toBe(0) expect(root.hoists.length).toBe(1)
expect((root.codegenNode as VNodeCall).children).toMatchObject([ expect((root.codegenNode as VNodeCall).children).toMatchObject([
{ {
type: NodeTypes.ELEMENT, type: NodeTypes.ELEMENT,
@ -200,7 +200,11 @@ describe('compiler: hoistStatic transform', () => {
}), }),
children: undefined, children: undefined,
patchFlag: genFlagText(PatchFlags.PROPS), patchFlag: genFlagText(PatchFlags.PROPS),
dynamicProps: `["id"]` dynamicProps: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: `_hoisted_1`,
isStatic: false
}
} }
} }
]) ])

View File

@ -288,7 +288,7 @@ export interface VNodeCall extends Node {
| ForRenderListExpression // v-for fragment call | ForRenderListExpression // v-for fragment call
| undefined | undefined
patchFlag: string | undefined patchFlag: string | undefined
dynamicProps: string | undefined dynamicProps: string | SimpleExpressionNode | undefined
directives: DirectiveArguments | undefined directives: DirectiveArguments | undefined
isBlock: boolean isBlock: boolean
disableTracking: boolean disableTracking: boolean

View File

@ -113,7 +113,7 @@ export interface TransformContext
onNodeRemoved(): void onNodeRemoved(): void
addIdentifiers(exp: ExpressionNode | string): void addIdentifiers(exp: ExpressionNode | string): void
removeIdentifiers(exp: ExpressionNode | string): void removeIdentifiers(exp: ExpressionNode | string): void
hoist(exp: JSChildNode): SimpleExpressionNode hoist(exp: string | JSChildNode): SimpleExpressionNode
cache<T extends JSChildNode>(exp: T, isVNode?: boolean): CacheExpression | T cache<T extends JSChildNode>(exp: T, isVNode?: boolean): CacheExpression | T
constantCache: Map<TemplateChildNode, ConstantTypes> constantCache: Map<TemplateChildNode, ConstantTypes>
@ -277,6 +277,7 @@ export function createTransformContext(
} }
}, },
hoist(exp) { hoist(exp) {
if (isString(exp)) exp = createSimpleExpression(exp, false)
context.hoists.push(exp) context.hoists.push(exp)
const identifier = createSimpleExpression( const identifier = createSimpleExpression(
`_hoisted_${context.hoists.length}`, `_hoisted_${context.hoists.length}`,

View File

@ -102,6 +102,9 @@ function walk(
codegenNode.props = context.hoist(props) codegenNode.props = context.hoist(props)
} }
} }
if (codegenNode.dynamicProps) {
codegenNode.dynamicProps = context.hoist(codegenNode.dynamicProps)
}
} }
} }
} else if (child.type === NodeTypes.TEXT_CALL) { } else if (child.type === NodeTypes.TEXT_CALL) {