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
This commit is contained in:
Chris Fritz 2016-07-28 23:40:18 -04:00 committed by Evan You
parent 7b3cb27d8a
commit 3e06c575cb
2 changed files with 48 additions and 11 deletions

View File

@ -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) {

View File

@ -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()