feat(compiler-core): support v-is
see https://github.com/vuejs/rfcs/pull/149 for details
This commit is contained in:
parent
d777ac6549
commit
b8ffbffaf7
@ -646,6 +646,55 @@ describe('compiler: parse', () => {
|
||||
})
|
||||
})
|
||||
|
||||
test('v-is without `isNativeTag`', () => {
|
||||
const ast = baseParse(
|
||||
`<div></div><div v-is="'foo'"></div><Comp></Comp>`,
|
||||
{
|
||||
isNativeTag: tag => tag === 'div'
|
||||
}
|
||||
)
|
||||
|
||||
expect(ast.children[0]).toMatchObject({
|
||||
type: NodeTypes.ELEMENT,
|
||||
tag: 'div',
|
||||
tagType: ElementTypes.ELEMENT
|
||||
})
|
||||
|
||||
expect(ast.children[1]).toMatchObject({
|
||||
type: NodeTypes.ELEMENT,
|
||||
tag: 'div',
|
||||
tagType: ElementTypes.COMPONENT
|
||||
})
|
||||
|
||||
expect(ast.children[2]).toMatchObject({
|
||||
type: NodeTypes.ELEMENT,
|
||||
tag: 'Comp',
|
||||
tagType: ElementTypes.COMPONENT
|
||||
})
|
||||
})
|
||||
|
||||
test('v-is with `isNativeTag`', () => {
|
||||
const ast = baseParse(`<div></div><div v-is="'foo'"></div><Comp></Comp>`)
|
||||
|
||||
expect(ast.children[0]).toMatchObject({
|
||||
type: NodeTypes.ELEMENT,
|
||||
tag: 'div',
|
||||
tagType: ElementTypes.ELEMENT
|
||||
})
|
||||
|
||||
expect(ast.children[1]).toMatchObject({
|
||||
type: NodeTypes.ELEMENT,
|
||||
tag: 'div',
|
||||
tagType: ElementTypes.COMPONENT
|
||||
})
|
||||
|
||||
expect(ast.children[2]).toMatchObject({
|
||||
type: NodeTypes.ELEMENT,
|
||||
tag: 'Comp',
|
||||
tagType: ElementTypes.COMPONENT
|
||||
})
|
||||
})
|
||||
|
||||
test('custom element', () => {
|
||||
const ast = baseParse('<div></div><comp></comp>', {
|
||||
isNativeTag: tag => tag === 'div',
|
||||
|
@ -829,6 +829,25 @@ describe('compiler: element transform', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('v-is', () => {
|
||||
const { node, root } = parseWithBind(`<div v-is="'foo'" />`)
|
||||
expect(root.helpers).toContain(RESOLVE_DYNAMIC_COMPONENT)
|
||||
expect(node).toMatchObject({
|
||||
tag: {
|
||||
callee: RESOLVE_DYNAMIC_COMPONENT,
|
||||
arguments: [
|
||||
{
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `'foo'`,
|
||||
isStatic: false
|
||||
}
|
||||
]
|
||||
},
|
||||
// should skip v-is runtime check
|
||||
directives: undefined
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
test('<svg> should be forced into blocks', () => {
|
||||
|
@ -451,9 +451,13 @@ function parseTag(
|
||||
let tagType = ElementTypes.ELEMENT
|
||||
const options = context.options
|
||||
if (!context.inPre && !options.isCustomElement(tag)) {
|
||||
if (options.isNativeTag) {
|
||||
const hasVIs = props.some(
|
||||
p => p.type === NodeTypes.DIRECTIVE && p.name === 'is'
|
||||
)
|
||||
if (options.isNativeTag && !hasVIs) {
|
||||
if (!options.isNativeTag(tag)) tagType = ElementTypes.COMPONENT
|
||||
} else if (
|
||||
hasVIs ||
|
||||
isCoreComponent(tag) ||
|
||||
(options.isBuiltInComponent && options.isBuiltInComponent(tag)) ||
|
||||
/^[A-Z]/.test(tag) ||
|
||||
|
@ -36,7 +36,8 @@ import {
|
||||
toValidAssetId,
|
||||
findProp,
|
||||
isCoreComponent,
|
||||
isBindKey
|
||||
isBindKey,
|
||||
findDir
|
||||
} from '../utils'
|
||||
import { buildSlots } from './vSlot'
|
||||
import { isStaticNode } from './hoistStatic'
|
||||
@ -202,7 +203,8 @@ export function resolveComponentType(
|
||||
const { tag } = node
|
||||
|
||||
// 1. dynamic component
|
||||
const isProp = node.tag === 'component' && findProp(node, 'is')
|
||||
const isProp =
|
||||
node.tag === 'component' ? findProp(node, 'is') : findDir(node, 'is')
|
||||
if (isProp) {
|
||||
const exp =
|
||||
isProp.type === NodeTypes.ATTRIBUTE
|
||||
@ -340,8 +342,11 @@ export function buildProps(
|
||||
if (name === 'once') {
|
||||
continue
|
||||
}
|
||||
// skip :is on <component>
|
||||
if (isBind && tag === 'component' && isBindKey(arg, 'is')) {
|
||||
// skip v-is and :is on <component>
|
||||
if (
|
||||
name === 'is' ||
|
||||
(isBind && tag === 'component' && isBindKey(arg, 'is'))
|
||||
) {
|
||||
continue
|
||||
}
|
||||
// skip v-on in SSR compilation
|
||||
|
Loading…
Reference in New Issue
Block a user