Преглед изворни кода

fix(compiler-core): should pre-convert text nodes in all non-element cases

Evan You пре 6 година
родитељ
комит
42f3f9e832
1 измењених фајлова са 39 додато и 28 уклоњено
  1. 39 28
      packages/compiler-core/src/transforms/transformText.ts

+ 39 - 28
packages/compiler-core/src/transforms/transformText.ts

@@ -6,7 +6,8 @@ import {
   InterpolationNode,
   CompoundExpressionNode,
   createCallExpression,
-  CallExpression
+  CallExpression,
+  ElementTypes
 } from '../ast'
 import { CREATE_TEXT } from '../runtimeHelpers'
 import { PatchFlags, PatchFlagNames } from '@vue/shared'
@@ -53,33 +54,43 @@ export const transformText: NodeTransform = (node, context) => {
         }
       }
 
-      if (hasText && children.length > 1) {
-        // when an element has mixed text/element children, convert text nodes
-        // into createTextVNode(text) calls.
-        for (let i = 0; i < children.length; i++) {
-          const child = children[i]
-          if (isText(child) || child.type === NodeTypes.COMPOUND_EXPRESSION) {
-            const callArgs: CallExpression['arguments'] = []
-            // createTextVNode defaults to single whitespace, so if it is a
-            // single space the code could be an empty call to save bytes.
-            if (child.type !== NodeTypes.TEXT || child.content !== ' ') {
-              callArgs.push(child)
-            }
-            // mark dynamic text with flag so it gets patched inside a block
-            if (child.type !== NodeTypes.TEXT) {
-              callArgs.push(
-                `${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`
-              )
-            }
-            children[i] = {
-              type: NodeTypes.TEXT_CALL,
-              content: child,
-              loc: child.loc,
-              codegenNode: createCallExpression(
-                context.helper(CREATE_TEXT),
-                callArgs
-              )
-            }
+      if (
+        !hasText ||
+        // if this is a plain element with a single text child, leave it as-is
+        // since the runtime has dedicated fast path for this by directly
+        // setting textContent of the element.
+        (node.type === NodeTypes.ELEMENT &&
+          node.tagType === ElementTypes.ELEMENT &&
+          children.length === 1)
+      ) {
+        return
+      }
+
+      // pre-convert text nodes into createTextVNode(text) calls to avoid
+      // runtime normalization.
+      for (let i = 0; i < children.length; i++) {
+        const child = children[i]
+        if (isText(child) || child.type === NodeTypes.COMPOUND_EXPRESSION) {
+          const callArgs: CallExpression['arguments'] = []
+          // createTextVNode defaults to single whitespace, so if it is a
+          // single space the code could be an empty call to save bytes.
+          if (child.type !== NodeTypes.TEXT || child.content !== ' ') {
+            callArgs.push(child)
+          }
+          // mark dynamic text with flag so it gets patched inside a block
+          if (child.type !== NodeTypes.TEXT) {
+            callArgs.push(
+              `${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`
+            )
+          }
+          children[i] = {
+            type: NodeTypes.TEXT_CALL,
+            content: child,
+            loc: child.loc,
+            codegenNode: createCallExpression(
+              context.helper(CREATE_TEXT),
+              callArgs
+            )
           }
         }
       }