feat(compiler): block optimization codegen for RootNode

This commit is contained in:
Evan You
2019-10-02 13:11:07 -04:00
parent c0bf341748
commit 24bd6c27e0
15 changed files with 376 additions and 491 deletions

View File

@@ -27,7 +27,7 @@ import {
TO_HANDLERS
} from '../runtimeConstants'
import { getInnerRange } from '../utils'
import { buildSlots } from './vSlot'
import { buildSlots, isVSlot } from './vSlot'
const toValidId = (str: string): string => str.replace(/[^\w]/g, '')
@@ -36,7 +36,10 @@ export const transformElement: NodeTransform = (node, context) => {
if (node.type === NodeTypes.ELEMENT) {
if (
node.tagType === ElementTypes.ELEMENT ||
node.tagType === ElementTypes.COMPONENT
node.tagType === ElementTypes.COMPONENT ||
// <template> with v-if or v-for are ignored during traversal.
// <template> without v-slot should be treated as a normal element.
(node.tagType === ElementTypes.TEMPLATE && !node.props.some(isVSlot))
) {
// perform the work on exit, after all child expressions have been
// processed and merged.

View File

@@ -19,7 +19,7 @@ import {
CallExpression
} from '../ast'
import { createCompilerError, ErrorCodes } from '../errors'
import { getInnerRange, findProp } from '../utils'
import { getInnerRange, findProp, createBlockExpression } from '../utils'
import {
RENDER_LIST,
OPEN_BLOCK,
@@ -69,7 +69,8 @@ export const transformFor = createStructuralDirectiveTransform(
valueAlias: value,
keyAlias: key,
objectIndexAlias: index,
children: [node],
children:
node.tagType === ElementTypes.TEMPLATE ? node.children : [node],
codegenNode
})
@@ -126,6 +127,8 @@ export const transformFor = createStructuralDirectiveTransform(
}
let childBlockChildren: TemplateChildNode[] | CallExpression =
node.children
// if the only child is a <slot/>, use it directly as fragment
// children since it already returns an array.
if (childBlockChildren.length === 1) {
const child = childBlockChildren[0]
if (
@@ -135,22 +138,17 @@ export const transformFor = createStructuralDirectiveTransform(
childBlockChildren = child.codegenNode!
}
}
childBlock = createSequenceExpression([
createCallExpression(helper(OPEN_BLOCK)),
createCallExpression(helper(CREATE_BLOCK), [
helper(FRAGMENT),
childBlockProps,
childBlockChildren
])
])
childBlock = createBlockExpression(
[helper(FRAGMENT), childBlockProps, childBlockChildren],
context
)
} else {
// Normal element v-for. Directly use the child's codegenNode,
// Normal element v-for. Directly use the child's codegenNode arguments,
// but replace createVNode() with createBlock()
node.codegenNode!.callee = helper(CREATE_BLOCK)
childBlock = createSequenceExpression([
createCallExpression(helper(OPEN_BLOCK)),
node.codegenNode!
])
childBlock = createBlockExpression(
node.codegenNode!.arguments,
context
)
}
renderExp.arguments.push(

View File

@@ -17,7 +17,7 @@ import { TransformContext, NodeTransform } from '../transform'
import { createCompilerError, ErrorCodes } from '../errors'
import { isString } from '@vue/shared'
const isVSlot = (p: ElementNode['props'][0]): p is DirectiveNode =>
export const isVSlot = (p: ElementNode['props'][0]): p is DirectiveNode =>
p.type === NodeTypes.DIRECTIVE && p.name === 'slot'
// A NodeTransform that tracks scope identifiers for scoped slots so that they