feat(compiler-core): support <portal> in template (#203)
This commit is contained in:
parent
37cbd0098d
commit
4547d85a38
@ -6,7 +6,8 @@ import {
|
|||||||
RESOLVE_DIRECTIVE,
|
RESOLVE_DIRECTIVE,
|
||||||
APPLY_DIRECTIVES,
|
APPLY_DIRECTIVES,
|
||||||
TO_HANDLERS,
|
TO_HANDLERS,
|
||||||
helperNameMap
|
helperNameMap,
|
||||||
|
PORTAL
|
||||||
} from '../../src/runtimeHelpers'
|
} from '../../src/runtimeHelpers'
|
||||||
import {
|
import {
|
||||||
CallExpression,
|
CallExpression,
|
||||||
@ -255,6 +256,52 @@ describe('compiler: element transform', () => {
|
|||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('should handle <portal> element', () => {
|
||||||
|
const { node } = parseWithElementTransform(
|
||||||
|
`<portal target="#foo"><span /></portal>`
|
||||||
|
)
|
||||||
|
expect(node.callee).toBe(CREATE_VNODE)
|
||||||
|
expect(node.arguments).toMatchObject([
|
||||||
|
PORTAL,
|
||||||
|
createObjectMatcher({
|
||||||
|
target: '#foo'
|
||||||
|
}),
|
||||||
|
[
|
||||||
|
{
|
||||||
|
type: NodeTypes.ELEMENT,
|
||||||
|
tag: 'span',
|
||||||
|
codegenNode: {
|
||||||
|
callee: CREATE_VNODE,
|
||||||
|
arguments: [`"span"`]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should handle <Portal> element', () => {
|
||||||
|
const { node } = parseWithElementTransform(
|
||||||
|
`<Portal target="#foo"><span /></Portal>`
|
||||||
|
)
|
||||||
|
expect(node.callee).toBe(CREATE_VNODE)
|
||||||
|
expect(node.arguments).toMatchObject([
|
||||||
|
PORTAL,
|
||||||
|
createObjectMatcher({
|
||||||
|
target: '#foo'
|
||||||
|
}),
|
||||||
|
[
|
||||||
|
{
|
||||||
|
type: NodeTypes.ELEMENT,
|
||||||
|
tag: 'span',
|
||||||
|
codegenNode: {
|
||||||
|
callee: CREATE_VNODE,
|
||||||
|
arguments: [`"span"`]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
test('error on v-bind with no argument', () => {
|
test('error on v-bind with no argument', () => {
|
||||||
const onError = jest.fn()
|
const onError = jest.fn()
|
||||||
parseWithElementTransform(`<div v-bind/>`, { onError })
|
parseWithElementTransform(`<div v-bind/>`, { onError })
|
||||||
|
@ -49,7 +49,8 @@ export const enum ElementTypes {
|
|||||||
ELEMENT,
|
ELEMENT,
|
||||||
COMPONENT,
|
COMPONENT,
|
||||||
SLOT,
|
SLOT,
|
||||||
TEMPLATE
|
TEMPLATE,
|
||||||
|
PORTAL
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Node {
|
export interface Node {
|
||||||
@ -99,6 +100,7 @@ export type ElementNode =
|
|||||||
| ComponentNode
|
| ComponentNode
|
||||||
| SlotOutletNode
|
| SlotOutletNode
|
||||||
| TemplateNode
|
| TemplateNode
|
||||||
|
| PortalNode
|
||||||
|
|
||||||
export interface BaseElementNode extends Node {
|
export interface BaseElementNode extends Node {
|
||||||
type: NodeTypes.ELEMENT
|
type: NodeTypes.ELEMENT
|
||||||
@ -134,6 +136,11 @@ export interface TemplateNode extends BaseElementNode {
|
|||||||
| undefined
|
| undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PortalNode extends BaseElementNode {
|
||||||
|
tagType: ElementTypes.PORTAL
|
||||||
|
codegenNode: ElementCodegenNode | undefined
|
||||||
|
}
|
||||||
|
|
||||||
export interface TextNode extends Node {
|
export interface TextNode extends Node {
|
||||||
type: NodeTypes.TEXT
|
type: NodeTypes.TEXT
|
||||||
content: string
|
content: string
|
||||||
|
@ -445,6 +445,7 @@ function parseTag(
|
|||||||
|
|
||||||
if (tag === 'slot') tagType = ElementTypes.SLOT
|
if (tag === 'slot') tagType = ElementTypes.SLOT
|
||||||
else if (tag === 'template') tagType = ElementTypes.TEMPLATE
|
else if (tag === 'template') tagType = ElementTypes.TEMPLATE
|
||||||
|
else if (tag === 'portal' || tag === 'Portal') tagType = ElementTypes.PORTAL
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -23,7 +23,8 @@ import {
|
|||||||
RESOLVE_DIRECTIVE,
|
RESOLVE_DIRECTIVE,
|
||||||
RESOLVE_COMPONENT,
|
RESOLVE_COMPONENT,
|
||||||
MERGE_PROPS,
|
MERGE_PROPS,
|
||||||
TO_HANDLERS
|
TO_HANDLERS,
|
||||||
|
PORTAL
|
||||||
} from '../runtimeHelpers'
|
} from '../runtimeHelpers'
|
||||||
import { getInnerRange, isVSlot, toValidAssetId } from '../utils'
|
import { getInnerRange, isVSlot, toValidAssetId } from '../utils'
|
||||||
import { buildSlots } from './vSlot'
|
import { buildSlots } from './vSlot'
|
||||||
@ -38,6 +39,7 @@ export const transformElement: NodeTransform = (node, context) => {
|
|||||||
if (
|
if (
|
||||||
node.tagType === ElementTypes.ELEMENT ||
|
node.tagType === ElementTypes.ELEMENT ||
|
||||||
node.tagType === ElementTypes.COMPONENT ||
|
node.tagType === ElementTypes.COMPONENT ||
|
||||||
|
node.tagType === ElementTypes.PORTAL ||
|
||||||
// <template> with v-if or v-for are ignored during traversal.
|
// <template> with v-if or v-for are ignored during traversal.
|
||||||
// <template> without v-slot should be treated as a normal element.
|
// <template> without v-slot should be treated as a normal element.
|
||||||
(node.tagType === ElementTypes.TEMPLATE && !node.props.some(isVSlot))
|
(node.tagType === ElementTypes.TEMPLATE && !node.props.some(isVSlot))
|
||||||
@ -46,6 +48,7 @@ export const transformElement: NodeTransform = (node, context) => {
|
|||||||
// processed and merged.
|
// processed and merged.
|
||||||
return () => {
|
return () => {
|
||||||
const isComponent = node.tagType === ElementTypes.COMPONENT
|
const isComponent = node.tagType === ElementTypes.COMPONENT
|
||||||
|
const isPortal = node.tagType === ElementTypes.PORTAL
|
||||||
let hasProps = node.props.length > 0
|
let hasProps = node.props.length > 0
|
||||||
let patchFlag: number = 0
|
let patchFlag: number = 0
|
||||||
let runtimeDirectives: DirectiveNode[] | undefined
|
let runtimeDirectives: DirectiveNode[] | undefined
|
||||||
@ -57,7 +60,11 @@ export const transformElement: NodeTransform = (node, context) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const args: CallExpression['arguments'] = [
|
const args: CallExpression['arguments'] = [
|
||||||
isComponent ? toValidAssetId(node.tag, `component`) : `"${node.tag}"`
|
isComponent
|
||||||
|
? toValidAssetId(node.tag, `component`)
|
||||||
|
: isPortal
|
||||||
|
? context.helper(PORTAL)
|
||||||
|
: `"${node.tag}"`
|
||||||
]
|
]
|
||||||
// props
|
// props
|
||||||
if (hasProps) {
|
if (hasProps) {
|
||||||
|
Loading…
Reference in New Issue
Block a user