fix(transition): warn only when there is more than one rendered child (#903)
This commit is contained in:
parent
449ab039fe
commit
37b1dc8242
@ -0,0 +1,140 @@
|
|||||||
|
import { compile } from '../../src'
|
||||||
|
|
||||||
|
describe('compiler warnings', () => {
|
||||||
|
describe('Transition', () => {
|
||||||
|
function checkWarning(
|
||||||
|
template: string,
|
||||||
|
shouldWarn: boolean,
|
||||||
|
message = `<Transition> expects exactly one child element or component.`
|
||||||
|
) {
|
||||||
|
const spy = jest.fn()
|
||||||
|
compile(template.trim(), {
|
||||||
|
hoistStatic: true,
|
||||||
|
transformHoist: null,
|
||||||
|
onError: err => {
|
||||||
|
spy(err.message)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (shouldWarn) expect(spy).toHaveBeenCalledWith(message)
|
||||||
|
else expect(spy).not.toHaveBeenCalled()
|
||||||
|
}
|
||||||
|
|
||||||
|
test('warns if multiple children', () => {
|
||||||
|
checkWarning(
|
||||||
|
`
|
||||||
|
<transition>
|
||||||
|
<div>hey</div>
|
||||||
|
<div>hey</div>
|
||||||
|
</transition>
|
||||||
|
`,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('warns with v-for', () => {
|
||||||
|
checkWarning(
|
||||||
|
`
|
||||||
|
<transition>
|
||||||
|
<div v-for="i in items">hey</div>
|
||||||
|
</transition>
|
||||||
|
`,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('warns with multiple v-if + v-for', () => {
|
||||||
|
checkWarning(
|
||||||
|
`
|
||||||
|
<transition>
|
||||||
|
<div v-if="a" v-for="i in items">hey</div>
|
||||||
|
<div v-else v-for="i in items">hey</div>
|
||||||
|
</transition>
|
||||||
|
`,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('warns with template v-if', () => {
|
||||||
|
checkWarning(
|
||||||
|
`
|
||||||
|
<transition>
|
||||||
|
<template v-if="ok"></template>
|
||||||
|
</transition>
|
||||||
|
`,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('warns with multiple templates', () => {
|
||||||
|
checkWarning(
|
||||||
|
`
|
||||||
|
<transition>
|
||||||
|
<template v-if="a"></template>
|
||||||
|
<template v-else></template>
|
||||||
|
</transition>
|
||||||
|
`,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('warns if multiple children with v-if', () => {
|
||||||
|
checkWarning(
|
||||||
|
`
|
||||||
|
<transition>
|
||||||
|
<div v-if="one">hey</div>
|
||||||
|
<div v-if="other">hey</div>
|
||||||
|
</transition>
|
||||||
|
`,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('does not warn with regular element', () => {
|
||||||
|
checkWarning(
|
||||||
|
`
|
||||||
|
<transition>
|
||||||
|
<div>hey</div>
|
||||||
|
</transition>
|
||||||
|
`,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('does not warn with one single v-if', () => {
|
||||||
|
checkWarning(
|
||||||
|
`
|
||||||
|
<transition>
|
||||||
|
<div v-if="a">hey</div>
|
||||||
|
</transition>
|
||||||
|
`,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('does not warn with v-if v-else-if v-else', () => {
|
||||||
|
checkWarning(
|
||||||
|
`
|
||||||
|
<transition>
|
||||||
|
<div v-if="a">hey</div>
|
||||||
|
<div v-else-if="b">hey</div>
|
||||||
|
<div v-else>hey</div>
|
||||||
|
</transition>
|
||||||
|
`,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('does not warn with v-if v-else', () => {
|
||||||
|
checkWarning(
|
||||||
|
`
|
||||||
|
<transition>
|
||||||
|
<div v-if="a">hey</div>
|
||||||
|
<div v-else>hey</div>
|
||||||
|
</transition>
|
||||||
|
`,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@ -1,4 +1,10 @@
|
|||||||
import { NodeTransform, NodeTypes, ElementTypes } from '@vue/compiler-core'
|
import {
|
||||||
|
NodeTransform,
|
||||||
|
NodeTypes,
|
||||||
|
ElementTypes,
|
||||||
|
ComponentNode,
|
||||||
|
IfBranchNode
|
||||||
|
} from '@vue/compiler-core'
|
||||||
import { TRANSITION } from '../runtimeHelpers'
|
import { TRANSITION } from '../runtimeHelpers'
|
||||||
import { createDOMCompilerError, DOMErrorCodes } from '../errors'
|
import { createDOMCompilerError, DOMErrorCodes } from '../errors'
|
||||||
|
|
||||||
@ -8,17 +14,30 @@ export const warnTransitionChildren: NodeTransform = (node, context) => {
|
|||||||
node.tagType === ElementTypes.COMPONENT
|
node.tagType === ElementTypes.COMPONENT
|
||||||
) {
|
) {
|
||||||
const component = context.isBuiltInComponent(node.tag)
|
const component = context.isBuiltInComponent(node.tag)
|
||||||
if (
|
if (component === TRANSITION) {
|
||||||
component === TRANSITION &&
|
return () => {
|
||||||
(node.children.length > 1 || node.children[0].type === NodeTypes.FOR)
|
if (node.children.length && hasMultipleChildren(node)) {
|
||||||
) {
|
|
||||||
context.onError(
|
context.onError(
|
||||||
createDOMCompilerError(DOMErrorCodes.X_TRANSITION_INVALID_CHILDREN, {
|
createDOMCompilerError(
|
||||||
|
DOMErrorCodes.X_TRANSITION_INVALID_CHILDREN,
|
||||||
|
{
|
||||||
start: node.children[0].loc.start,
|
start: node.children[0].loc.start,
|
||||||
end: node.children[node.children.length - 1].loc.end,
|
end: node.children[node.children.length - 1].loc.end,
|
||||||
source: ''
|
source: ''
|
||||||
})
|
}
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasMultipleChildren(node: ComponentNode | IfBranchNode): boolean {
|
||||||
|
const child = node.children[0]
|
||||||
|
return (
|
||||||
|
node.children.length !== 1 ||
|
||||||
|
child.type === NodeTypes.FOR ||
|
||||||
|
(child.type === NodeTypes.IF && child.branches.some(hasMultipleChildren))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user