Browse Source

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
dev
Chris Fritz 8 years ago
committed by Evan You
parent
commit
3e06c575cb
  1. 30
      src/compiler/parser/index.js
  2. 29
      test/unit/modules/compiler/parser.spec.js

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

29
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('<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()

Loading…
Cancel
Save