feat(compiler-core): do not generate TEXT flag if child is constant

This commit is contained in:
Evan You
2019-10-16 12:00:55 -04:00
parent 6607edab2d
commit 6a75c3463b
5 changed files with 52 additions and 13 deletions

View File

@@ -15,9 +15,8 @@ import { APPLY_DIRECTIVES } from '../runtimeHelpers'
import { PatchFlags, isString, isSymbol } from '@vue/shared'
import { isSlotOutlet, findProp } from '../utils'
function hasDynamicKey(node: ElementNode) {
const keyProp = findProp(node, 'key')
return keyProp && keyProp.type === NodeTypes.DIRECTIVE
function hasDynamicKeyOrRef(node: ElementNode) {
return findProp(node, 'key', true) || findProp(node, 'ref', true)
}
export function hoistStatic(root: RootNode, context: TransformContext) {
@@ -57,7 +56,7 @@ function walk(
if (
!doNotHoistNode &&
isStaticNode(child, resultCache) &&
!hasDynamicKey(child)
!hasDynamicKeyOrRef(child)
) {
// whole tree is static
child.codegenNode = context.hoist(child.codegenNode!)
@@ -70,7 +69,7 @@ function walk(
(!flag ||
flag === PatchFlags.NEED_PATCH ||
flag === PatchFlags.TEXT) &&
!hasDynamicKey(child)
!hasDynamicKeyOrRef(child)
) {
let codegenNode = child.codegenNode as ElementCodegenNode
if (codegenNode.callee === APPLY_DIRECTIVES) {
@@ -107,9 +106,9 @@ function getPatchFlag(node: PlainElementNode): number | undefined {
return flag ? parseInt(flag, 10) : undefined
}
function isStaticNode(
export function isStaticNode(
node: TemplateChildNode | SimpleExpressionNode,
resultCache: Map<TemplateChildNode, boolean>
resultCache: Map<TemplateChildNode, boolean> = new Map()
): boolean {
switch (node.type) {
case NodeTypes.ELEMENT:
@@ -121,7 +120,7 @@ function isStaticNode(
return cached
}
const flag = getPatchFlag(node)
if (!flag || flag === PatchFlags.TEXT) {
if (!flag) {
// element self is static. check its children.
for (let i = 0; i < node.children.length; i++) {
if (!isStaticNode(node.children[i], resultCache)) {

View File

@@ -28,6 +28,7 @@ import {
} from '../runtimeHelpers'
import { getInnerRange, isVSlot, toValidAssetId } from '../utils'
import { buildSlots } from './vSlot'
import { isStaticNode } from './hoistStatic'
// some directive transforms (e.g. v-model) may return a symbol for runtime
// import, which should be used instead of a resolveDirective call.
@@ -93,10 +94,11 @@ export const transformElement: NodeTransform = (node, context) => {
} else if (node.children.length === 1) {
const child = node.children[0]
const type = child.type
// check for dynamic text children
const hasDynamicTextChild =
type === NodeTypes.INTERPOLATION ||
type === NodeTypes.COMPOUND_EXPRESSION
if (hasDynamicTextChild) {
if (hasDynamicTextChild && !isStaticNode(child)) {
patchFlag |= PatchFlags.TEXT
}
// pass directly if the only child is a text node