Jelajahi Sumber

warn when template contains text outside root element (#5164)

* warn when template contains text outside root element

* fix warned flag

* make warn once a function
AchillesJ 9 tahun lalu
induk
melakukan
c6ab2e06d4
2 mengubah file dengan 32 tambahan dan 13 penghapusan
  1. 22 13
      src/compiler/parser/index.js
  2. 10 0
      test/unit/modules/compiler/parser.spec.js

+ 22 - 13
src/compiler/parser/index.js

@@ -63,6 +63,13 @@ export function parse (
   let inPre = false
   let warned = false
 
+  function warnOnce (msg) {
+    if (!warned) {
+      warned = true
+      warn(msg)
+    }
+  }
+
   function endPre (element) {
     // check pre state
     if (element.pre) {
@@ -146,17 +153,15 @@ export function parse (
       }
 
       function checkRootConstraints (el) {
-        if (process.env.NODE_ENV !== 'production' && !warned) {
+        if (process.env.NODE_ENV !== 'production') {
           if (el.tag === 'slot' || el.tag === 'template') {
-            warned = true
-            warn(
+            warnOnce(
               `Cannot use <${el.tag}> as component root element because it may ` +
               'contain multiple nodes.'
             )
           }
           if (el.attrsMap.hasOwnProperty('v-for')) {
-            warned = true
-            warn(
+            warnOnce(
               'Cannot use v-for on stateful component root element because ' +
               'it renders multiple elements.'
             )
@@ -176,9 +181,8 @@ export function parse (
             exp: element.elseif,
             block: element
           })
-        } else if (process.env.NODE_ENV !== 'production' && !warned) {
-          warned = true
-          warn(
+        } else if (process.env.NODE_ENV !== 'production') {
+          warnOnce(
             `Component template should contain exactly one root element. ` +
             `If you are using v-if on multiple elements, ` +
             `use v-else-if to chain them instead.`
@@ -224,11 +228,16 @@ export function parse (
 
     chars (text: string) {
       if (!currentParent) {
-        if (process.env.NODE_ENV !== 'production' && !warned && text === template) {
-          warned = true
-          warn(
-            'Component template requires a root element, rather than just text.'
-          )
+        if (process.env.NODE_ENV !== 'production') {
+          if (text === template) {
+            warnOnce(
+              'Component template requires a root element, rather than just text.'
+            )
+          } else if ((text = text.trim())) {
+            warnOnce(
+              `text "${text}" outside root element will be ignored.`
+            )
+          }
         }
         return
       }

+ 10 - 0
test/unit/modules/compiler/parser.spec.js

@@ -77,6 +77,16 @@ describe('parser', () => {
     expect('Component template requires a root element, rather than just text').toHaveBeenWarned()
   })
 
+  it('warn text before root element', () => {
+    parse('before root {{ interpolation }}<div></div>', baseOptions)
+    expect('text "before root {{ interpolation }}" outside root element will be ignored.').toHaveBeenWarned()
+  })
+
+  it('warn text after root element', () => {
+    parse('<div></div>after root {{ interpolation }}', baseOptions)
+    expect('text "after root {{ interpolation }}" outside root element will be ignored.').toHaveBeenWarned()
+  })
+
   it('warn multiple root elements', () => {
     parse('<div></div><div></div>', baseOptions)
     expect('Component template should contain exactly one root element').toHaveBeenWarned()