Skip to content

Commit

Permalink
Allow 2 root nodes with v-if and v-else (vuejs#3329)
Browse files Browse the repository at this point in the history
* allow 2 root nodes with v-if and v-else

* apply root constraints to 2nd root element with v-else
  • Loading branch information
chrisvfritz authored and yyx990803 committed Jul 29, 2016
1 parent 7b3cb27 commit 3e06c57
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 11 deletions.
30 changes: 19 additions & 11 deletions src/compiler/parser/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
29 changes: 29 additions & 0 deletions test/unit/modules/compiler/parser.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,35 @@ describe('parser', () => {
expect('Component template should contain exactly one root element').toHaveBeenWarned()
})

it('warn multiple root elements', () => {
parse('<div></div><div></div>', baseOptions)
expect('Component template should contain exactly one root element:\n\n<div></div><div></div>').toHaveBeenWarned()
})

it('not warn 2 root elements with v-if and v-else', () => {
parse('<div v-if="1"></div><div v-else></div>', baseOptions)
expect('Component template should contain exactly one root element:\n\n<div v-if="1"></div><div v-else></div>')
.not.toHaveBeenWarned()
})

it('warn 2 root elements with v-if', () => {
parse('<div v-if="1"></div><div v-if="2"></div>', baseOptions)
expect('Component template should contain exactly one root element:\n\n<div v-if="1"></div><div v-if="2"></div>')
.toHaveBeenWarned()
})

it('warn 3 root elements with v-if and v-else on first 2', () => {
parse('<div v-if="1"></div><div v-else></div><div></div>', baseOptions)
expect('Component template should contain exactly one root element:\n\n<div v-if="1"></div><div v-else></div><div></div>')
.toHaveBeenWarned()
})

it('warn 2 root elements with v-if and v-else with v-for on 2nd', () => {
parse('<div v-if="1"></div><div v-else v-for="i in [1]"></div>', baseOptions)
expect('Cannot use v-for on stateful component root element because it renders multiple elements:\n<div v-if="1"></div><div v-else v-for="i in [1]"></div>')
.toHaveBeenWarned()
})

it('warn <template> as root element', () => {
parse('<template></template>', baseOptions)
expect('Cannot use <template> as component root element').toHaveBeenWarned()
Expand Down

0 comments on commit 3e06c57

Please sign in to comment.