From 3e06c575cb547ff398b7effcc1bd277e5424af2d Mon Sep 17 00:00:00 2001 From: Chris Fritz Date: Thu, 28 Jul 2016 23:40:18 -0400 Subject: [PATCH] Allow 2 root nodes with v-if and v-else (#3329) * allow 2 root nodes with v-if and v-else * apply root constraints to 2nd root element with v-else --- src/compiler/parser/index.js | 30 ++++++++++++++--------- test/unit/modules/compiler/parser.spec.js | 29 ++++++++++++++++++++++ 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/compiler/parser/index.js b/src/compiler/parser/index.js index be8d87da..6d219bb5 100644 --- a/src/compiler/parser/index.js +++ b/src/compiler/parser/index.js @@ -130,29 +130,37 @@ export function parse ( processAttrs(element) } - // tree management - if (!root) { - root = element - // check root element constraints + function checkRootConstraints (el) { if (process.env.NODE_ENV !== 'production') { - if (tag === 'slot' || tag === 'template') { + if (el.tag === 'slot' || el.tag === 'template') { warn( - `Cannot use <${tag}> as component root element because it may ` + + `Cannot use <${el.tag}> as component root element because it may ` + 'contain multiple nodes:\n' + template ) } - if (element.attrsMap.hasOwnProperty('v-for')) { + if (el.attrsMap.hasOwnProperty('v-for')) { warn( 'Cannot use v-for on stateful component root element because ' + 'it renders multiple elements:\n' + template ) } } + } + + // tree management + if (!root) { + root = element + checkRootConstraints(root) } else if (process.env.NODE_ENV !== 'production' && !stack.length && !warned) { - warned = true - warn( - `Component template should contain exactly one root element:\n\n${template}` - ) + // allow 2 root elements with v-if and v-else + if ((root.attrsMap.hasOwnProperty('v-if') && element.attrsMap.hasOwnProperty('v-else'))) { + checkRootConstraints(element) + } else { + warned = true + warn( + `Component template should contain exactly one root element:\n\n${template}` + ) + } } if (currentParent && !element.forbidden) { if (element.else) { diff --git a/test/unit/modules/compiler/parser.spec.js b/test/unit/modules/compiler/parser.spec.js index 0574053e..56bfdbb2 100644 --- a/test/unit/modules/compiler/parser.spec.js +++ b/test/unit/modules/compiler/parser.spec.js @@ -76,6 +76,35 @@ describe('parser', () => { expect('Component template should contain exactly one root element').toHaveBeenWarned() }) + it('warn multiple root elements', () => { + parse('
', baseOptions) + expect('Component template should contain exactly one root element:\n\n
').toHaveBeenWarned() + }) + + it('not warn 2 root elements with v-if and v-else', () => { + parse('
', baseOptions) + expect('Component template should contain exactly one root element:\n\n
') + .not.toHaveBeenWarned() + }) + + it('warn 2 root elements with v-if', () => { + parse('
', baseOptions) + expect('Component template should contain exactly one root element:\n\n
') + .toHaveBeenWarned() + }) + + it('warn 3 root elements with v-if and v-else on first 2', () => { + parse('
', baseOptions) + expect('Component template should contain exactly one root element:\n\n
') + .toHaveBeenWarned() + }) + + it('warn 2 root elements with v-if and v-else with v-for on 2nd', () => { + parse('
', baseOptions) + expect('Cannot use v-for on stateful component root element because it renders multiple elements:\n
') + .toHaveBeenWarned() + }) + it('warn