RESOLVE_DIRECTIVE,
APPLY_DIRECTIVES,
TO_HANDLERS,
- helperNameMap
+ helperNameMap,
+ PORTAL
} from '../../src/runtimeHelpers'
import {
CallExpression,
])
})
+ 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', () => {
const onError = jest.fn()
parseWithElementTransform(`<div v-bind/>`, { onError })
ELEMENT,
COMPONENT,
SLOT,
- TEMPLATE
+ TEMPLATE,
+ PORTAL
}
export interface Node {
| ComponentNode
| SlotOutletNode
| TemplateNode
+ | PortalNode
export interface BaseElementNode extends Node {
type: NodeTypes.ELEMENT
| undefined
}
+export interface PortalNode extends BaseElementNode {
+ tagType: ElementTypes.PORTAL
+ codegenNode: ElementCodegenNode | undefined
+}
+
export interface TextNode extends Node {
type: NodeTypes.TEXT
content: string
if (tag === 'slot') tagType = ElementTypes.SLOT
else if (tag === 'template') tagType = ElementTypes.TEMPLATE
+ else if (tag === 'portal' || tag === 'Portal') tagType = ElementTypes.PORTAL
}
return {
RESOLVE_DIRECTIVE,
RESOLVE_COMPONENT,
MERGE_PROPS,
- TO_HANDLERS
+ TO_HANDLERS,
+ PORTAL
} from '../runtimeHelpers'
import { getInnerRange, isVSlot, toValidAssetId } from '../utils'
import { buildSlots } from './vSlot'
if (
node.tagType === ElementTypes.ELEMENT ||
node.tagType === ElementTypes.COMPONENT ||
+ node.tagType === ElementTypes.PORTAL ||
// <template> with v-if or v-for are ignored during traversal.
// <template> without v-slot should be treated as a normal element.
(node.tagType === ElementTypes.TEMPLATE && !node.props.some(isVSlot))
// processed and merged.
return () => {
const isComponent = node.tagType === ElementTypes.COMPONENT
+ const isPortal = node.tagType === ElementTypes.PORTAL
let hasProps = node.props.length > 0
let patchFlag: number = 0
let runtimeDirectives: DirectiveNode[] | undefined
}
const args: CallExpression['arguments'] = [
- isComponent ? toValidAssetId(node.tag, `component`) : `"${node.tag}"`
+ isComponent
+ ? toValidAssetId(node.tag, `component`)
+ : isPortal
+ ? context.helper(PORTAL)
+ : `"${node.tag}"`
]
// props
if (hasProps) {