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', () => {
|
test('custom element', () => {
|
||||||
const ast = baseParse('<div></div><comp></comp>', {
|
const ast = baseParse('<div></div><comp></comp>', {
|
||||||
isNativeTag: tag => tag === 'div',
|
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', () => {
|
test('<svg> should be forced into blocks', () => {
|
||||||
|
@ -451,9 +451,13 @@ function parseTag(
|
|||||||
let tagType = ElementTypes.ELEMENT
|
let tagType = ElementTypes.ELEMENT
|
||||||
const options = context.options
|
const options = context.options
|
||||||
if (!context.inPre && !options.isCustomElement(tag)) {
|
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
|
if (!options.isNativeTag(tag)) tagType = ElementTypes.COMPONENT
|
||||||
} else if (
|
} else if (
|
||||||
|
hasVIs ||
|
||||||
isCoreComponent(tag) ||
|
isCoreComponent(tag) ||
|
||||||
(options.isBuiltInComponent && options.isBuiltInComponent(tag)) ||
|
(options.isBuiltInComponent && options.isBuiltInComponent(tag)) ||
|
||||||
/^[A-Z]/.test(tag) ||
|
/^[A-Z]/.test(tag) ||
|
||||||
|
@ -36,7 +36,8 @@ import {
|
|||||||
toValidAssetId,
|
toValidAssetId,
|
||||||
findProp,
|
findProp,
|
||||||
isCoreComponent,
|
isCoreComponent,
|
||||||
isBindKey
|
isBindKey,
|
||||||
|
findDir
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
import { buildSlots } from './vSlot'
|
import { buildSlots } from './vSlot'
|
||||||
import { isStaticNode } from './hoistStatic'
|
import { isStaticNode } from './hoistStatic'
|
||||||
@ -202,7 +203,8 @@ export function resolveComponentType(
|
|||||||
const { tag } = node
|
const { tag } = node
|
||||||
|
|
||||||
// 1. dynamic component
|
// 1. dynamic component
|
||||||
const isProp = node.tag === 'component' && findProp(node, 'is')
|
const isProp =
|
||||||
|
node.tag === 'component' ? findProp(node, 'is') : findDir(node, 'is')
|
||||||
if (isProp) {
|
if (isProp) {
|
||||||
const exp =
|
const exp =
|
||||||
isProp.type === NodeTypes.ATTRIBUTE
|
isProp.type === NodeTypes.ATTRIBUTE
|
||||||
@ -340,8 +342,11 @@ export function buildProps(
|
|||||||
if (name === 'once') {
|
if (name === 'once') {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// skip :is on <component>
|
// skip v-is and :is on <component>
|
||||||
if (isBind && tag === 'component' && isBindKey(arg, 'is')) {
|
if (
|
||||||
|
name === 'is' ||
|
||||||
|
(isBind && tag === 'component' && isBindKey(arg, 'is'))
|
||||||
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// skip v-on in SSR compilation
|
// skip v-on in SSR compilation
|
||||||
|
Loading…
x
Reference in New Issue
Block a user