diff --git a/packages/runtime-vapor/__tests__/components/Teleport.spec.ts b/packages/runtime-vapor/__tests__/components/Teleport.spec.ts
index bad520872..d4282ab8a 100644
--- a/packages/runtime-vapor/__tests__/components/Teleport.spec.ts
+++ b/packages/runtime-vapor/__tests__/components/Teleport.spec.ts
@@ -2,6 +2,7 @@ import {
type LooseRawProps,
type VaporComponent,
createComponent as createComp,
+ createComponent,
} from '../../src/component'
import {
type VaporDirective,
@@ -9,15 +10,18 @@ import {
child,
createIf,
createTemplateRefSetter,
+ createVaporApp,
defineVaporComponent,
renderEffect,
setInsertionState,
setText,
template,
+ vaporInteropPlugin,
withVaporDirectives,
} from '@vue/runtime-vapor'
import { makeRender } from '../_utils'
import {
+ h,
nextTick,
onBeforeUnmount,
onMounted,
@@ -63,7 +67,7 @@ describe('renderer: VaporTeleport', () => {
mount(root)
expect(root.innerHTML).toBe(
- '
',
+ '',
)
})
@@ -116,7 +120,7 @@ describe('renderer: VaporTeleport', () => {
show.value = true
await nextTick()
expect(root.innerHTML).toBe(
- `Footer
`,
+ `Footer
`,
)
})
})
@@ -155,7 +159,9 @@ describe('renderer: VaporTeleport', () => {
createRecord(parentId, Parent as any)
mount(root)
- expect(root.innerHTML).toBe('root
')
+ expect(root.innerHTML).toBe(
+ 'root
',
+ )
expect(target.innerHTML).toBe('teleported
')
// rerender child
@@ -163,7 +169,9 @@ describe('renderer: VaporTeleport', () => {
return template('teleported 2
')()
})
- expect(root.innerHTML).toBe('root
')
+ expect(root.innerHTML).toBe(
+ 'root
',
+ )
expect(target.innerHTML).toBe('teleported 2
')
// rerender parent
@@ -181,7 +189,9 @@ describe('renderer: VaporTeleport', () => {
return [n0, n1]
})
- expect(root.innerHTML).toBe('root 2
')
+ expect(root.innerHTML).toBe(
+ 'root 2
',
+ )
expect(target.innerHTML).toBe('teleported 2
')
})
@@ -219,7 +229,7 @@ describe('renderer: VaporTeleport', () => {
mount(root)
expect(root.innerHTML).toBe(
- '',
+ '',
)
expect(target.innerHTML).toBe('')
@@ -241,14 +251,16 @@ describe('renderer: VaporTeleport', () => {
})
expect(root.innerHTML).toBe(
- '',
+ '',
)
expect(target.innerHTML).toBe('')
// toggle disabled
disabled.value = false
await nextTick()
- expect(root.innerHTML).toBe('')
+ expect(root.innerHTML).toBe(
+ '',
+ )
expect(target.innerHTML).toBe('teleported
')
})
@@ -300,7 +312,9 @@ describe('renderer: VaporTeleport', () => {
createRecord(parentId, Parent as any)
mount(root)
- expect(root.innerHTML).toBe('root
')
+ expect(root.innerHTML).toBe(
+ 'root
',
+ )
expect(target.innerHTML).toBe('teleported
')
// reload child by changing msg
@@ -318,7 +332,9 @@ describe('renderer: VaporTeleport', () => {
return [n0]
},
})
- expect(root.innerHTML).toBe('root
')
+ expect(root.innerHTML).toBe(
+ 'root
',
+ )
expect(target.innerHTML).toBe('teleported 2
')
// reload parent by changing msg
@@ -348,7 +364,9 @@ describe('renderer: VaporTeleport', () => {
},
})
- expect(root.innerHTML).toBe('root 2
')
+ expect(root.innerHTML).toBe(
+ 'root 2
',
+ )
expect(target.innerHTML).toBe('teleported 2
')
// reload parent again by changing disabled
@@ -379,7 +397,7 @@ describe('renderer: VaporTeleport', () => {
})
expect(root.innerHTML).toBe(
- 'teleported 2
root 2
',
+ 'teleported 2
root 2
',
)
expect(target.innerHTML).toBe('')
})
@@ -434,7 +452,7 @@ describe('renderer: VaporTeleport', () => {
mount(root)
expect(root.innerHTML).toBe(
- 'teleported
root
',
+ 'teleported
root
',
)
expect(target.innerHTML).toBe('')
@@ -454,7 +472,7 @@ describe('renderer: VaporTeleport', () => {
},
})
expect(root.innerHTML).toBe(
- 'teleported 2
root
',
+ 'teleported 2
root
',
)
expect(target.innerHTML).toBe('')
@@ -474,14 +492,16 @@ describe('renderer: VaporTeleport', () => {
},
})
expect(root.innerHTML).toBe(
- 'teleported 3
root
',
+ 'teleported 3
root
',
)
expect(target.innerHTML).toBe('')
// toggle disabled
disabled.value = false
await nextTick()
- expect(root.innerHTML).toBe('root
')
+ expect(root.innerHTML).toBe(
+ 'root
',
+ )
expect(target.innerHTML).toBe('teleported 3
')
})
@@ -537,7 +557,7 @@ describe('renderer: VaporTeleport', () => {
mount(root)
expect(root.innerHTML).toBe(
- 'teleported
childroot
',
+ 'teleported
childroot
',
)
expect(target.innerHTML).toBe('')
@@ -557,7 +577,7 @@ describe('renderer: VaporTeleport', () => {
},
})
expect(root.innerHTML).toBe(
- 'teleported 2
childroot
',
+ 'teleported 2
childroot
',
)
expect(target.innerHTML).toBe('')
@@ -577,17 +597,68 @@ describe('renderer: VaporTeleport', () => {
},
})
expect(root.innerHTML).toBe(
- 'teleported 3
childroot
',
+ 'teleported 3
childroot
',
)
expect(target.innerHTML).toBe('')
// toggle disabled
disabled.value = false
await nextTick()
- expect(root.innerHTML).toBe('root
')
+ expect(root.innerHTML).toBe(
+ 'root
',
+ )
expect(target.innerHTML).toBe('teleported 3
child')
})
})
+
+ describe('VDOM interop', () => {
+ test('render vdom component', async () => {
+ const target = document.createElement('div')
+ const root = document.createElement('div')
+
+ const VDOMComp = {
+ setup() {
+ return () => h('h1', null, 'vdom comp')
+ },
+ }
+
+ const disabled = ref(true)
+ const App = defineVaporComponent({
+ setup() {
+ const n1 = createComponent(
+ VaporTeleport,
+ {
+ to: () => target,
+ defer: () => '',
+ disabled: () => disabled.value,
+ },
+ {
+ default: () => {
+ const n0 = createComponent(VDOMComp)
+ return n0
+ },
+ },
+ true,
+ )
+ return n1
+ },
+ })
+
+ const app = createVaporApp(App)
+ app.use(vaporInteropPlugin)
+ app.mount(root)
+
+ expect(target.innerHTML).toBe('')
+ expect(root.innerHTML).toBe(
+ 'vdom comp
',
+ )
+
+ disabled.value = false
+ await nextTick()
+ expect(root.innerHTML).toBe('')
+ expect(target.innerHTML).toBe('vdom comp
')
+ })
+ })
})
function runSharedTests(deferMode: boolean): void {
@@ -625,7 +696,9 @@ function runSharedTests(deferMode: boolean): void {
}).create()
mount(root)
- expect(root.innerHTML).toBe('root
')
+ expect(root.innerHTML).toBe(
+ 'root
',
+ )
expect(target.innerHTML).toBe('teleported
')
})
@@ -654,14 +727,18 @@ function runSharedTests(deferMode: boolean): void {
}).create()
mount(root)
- expect(root.innerHTML).toBe('root
')
+ expect(root.innerHTML).toBe(
+ 'root
',
+ )
expect(targetA.innerHTML).toBe('teleported
')
expect(targetB.innerHTML).toBe('')
target.value = targetB
await nextTick()
- expect(root.innerHTML).toBe('root
')
+ expect(root.innerHTML).toBe(
+ 'root
',
+ )
expect(targetA.innerHTML).toBe('')
expect(targetB.innerHTML).toBe('teleported
')
})
@@ -834,7 +911,9 @@ function runSharedTests(deferMode: boolean): void {
},
}).create()
mount(root)
- expect(root.innerHTML).toBe('')
+ expect(root.innerHTML).toBe(
+ '',
+ )
expect(target.innerHTML).toBe('one
two')
// update existing content
@@ -849,7 +928,9 @@ function runSharedTests(deferMode: boolean): void {
// toggling
child1.value = [] as any
await nextTick()
- expect(root.innerHTML).toBe('')
+ expect(root.innerHTML).toBe(
+ '',
+ )
expect(target.innerHTML).toBe('three')
// toggle back
@@ -859,14 +940,18 @@ function runSharedTests(deferMode: boolean): void {
] as any
child2.value = [template('three')()] as any
await nextTick()
- expect(root.innerHTML).toBe('')
+ expect(root.innerHTML).toBe(
+ '',
+ )
// should append
expect(target.innerHTML).toBe('one
two
three')
// toggle the other teleport
child2.value = [] as any
await nextTick()
- expect(root.innerHTML).toBe('')
+ expect(root.innerHTML).toBe(
+ '',
+ )
expect(target.innerHTML).toBe('one
two
')
})
@@ -897,12 +982,12 @@ function runSharedTests(deferMode: boolean): void {
mount(root)
expect(root.innerHTML).toBe(
- 'teleported
',
+ 'teleported
',
)
disabled.value = false
await nextTick()
expect(root.innerHTML).toBe(
- '',
+ '',
)
})
@@ -929,13 +1014,15 @@ function runSharedTests(deferMode: boolean): void {
}).create()
mount(root)
- expect(root.innerHTML).toBe('root
')
+ expect(root.innerHTML).toBe(
+ 'root
',
+ )
expect(target.innerHTML).toBe('teleported
')
disabled.value = true
await nextTick()
expect(root.innerHTML).toBe(
- 'teleported
root
',
+ 'teleported
root
',
)
expect(target.innerHTML).toBe('')
@@ -943,7 +1030,7 @@ function runSharedTests(deferMode: boolean): void {
disabled.value = false
await nextTick()
expect(root.innerHTML).toBe(
- 'root
',
+ 'root
',
)
expect(target.innerHTML).toBe('teleported
')
})
@@ -984,14 +1071,14 @@ function runSharedTests(deferMode: boolean): void {
}).create()
mount(root)
- expect(root.innerHTML).toBe('')
+ expect(root.innerHTML).toBe('')
expect(target.innerHTML).toBe('foo
')
expect(spy).toHaveBeenCalledTimes(1)
expect(teardown).not.toHaveBeenCalled()
toggle.value = false
await nextTick()
- expect(root.innerHTML).toBe('')
+ expect(root.innerHTML).toBe('')
expect(target.innerHTML).toBe('')
expect(spy).toHaveBeenCalledTimes(1)
expect(teardown).toHaveBeenCalledTimes(1)
@@ -1078,7 +1165,9 @@ function runSharedTests(deferMode: boolean): void {
show.value = true
await nextTick()
- expect(root.innerHTML).toBe('teleported
')
+ expect(root.innerHTML).toBe(
+ 'teleported
',
+ )
show.value = false
await nextTick()
@@ -1125,7 +1214,7 @@ function runSharedTests(deferMode: boolean): void {
parentShow.value = true
await nextTick()
expect(root.innerHTML).toBe(
- 'foo
',
+ 'foo
',
)
parentShow.value = false
diff --git a/packages/runtime-vapor/src/block.ts b/packages/runtime-vapor/src/block.ts
index b980b3999..aeac078ae 100644
--- a/packages/runtime-vapor/src/block.ts
+++ b/packages/runtime-vapor/src/block.ts
@@ -110,12 +110,7 @@ export function insert(
if (block.insert) {
block.insert(parent, anchor, (block as TransitionBlock).$transition)
} else {
- insert(
- block.nodes,
- block.target || parent,
- block.targetAnchor || anchor,
- parentSuspense,
- )
+ insert(block.nodes, parent, anchor, parentSuspense)
}
}
}
diff --git a/packages/runtime-vapor/src/components/Teleport.ts b/packages/runtime-vapor/src/components/Teleport.ts
index d80399373..637985ddc 100644
--- a/packages/runtime-vapor/src/components/Teleport.ts
+++ b/packages/runtime-vapor/src/components/Teleport.ts
@@ -35,13 +35,12 @@ export const VaporTeleportImpl = {
)
const updateEffect = renderEffect(() => {
- frag.update(
- // access the props to trigger tracking
- extend(
- {},
- new Proxy(props, rawPropsProxyHandlers) as any as TeleportProps,
- ),
+ // access the props to trigger tracking
+ frag.props = extend(
+ {},
+ new Proxy(props, rawPropsProxyHandlers) as any as TeleportProps,
)
+ frag.update()
})
if (__DEV__) {
@@ -82,7 +81,10 @@ export const VaporTeleportImpl = {
}
export class TeleportFragment extends VaporFragment {
+ target?: ParentNode | null
+ targetAnchor?: Node | null
anchor: Node
+ props?: TeleportProps
private targetStart?: Node
private mainAnchor?: Node
@@ -92,7 +94,7 @@ export class TeleportFragment extends VaporFragment {
constructor() {
super([])
- this.anchor = __DEV__ ? createComment('teleport') : createTextNode()
+ this.anchor = createTextNode()
}
get currentParent(): ParentNode {
@@ -104,7 +106,7 @@ export class TeleportFragment extends VaporFragment {
}
get parent(): ParentNode | null {
- return this.anchor.parentNode
+ return this.anchor && this.anchor.parentNode
}
updateChildren(children: Block): void {
@@ -120,7 +122,10 @@ export class TeleportFragment extends VaporFragment {
insert((this.nodes = children), this.currentParent, this.currentAnchor)
}
- update(props: TeleportProps): void {
+ update(): void {
+ // not mounted yet
+ if (!this.parent) return
+
const mount = (parent: ParentNode, anchor: Node | null) => {
insert(
this.nodes,
@@ -130,7 +135,10 @@ export class TeleportFragment extends VaporFragment {
}
const mountToTarget = () => {
- const target = (this.target = resolveTeleportTarget(props, querySelector))
+ const target = (this.target = resolveTeleportTarget(
+ this.props!,
+ querySelector,
+ ))
if (target) {
if (
// initial mount into target
@@ -153,29 +161,12 @@ export class TeleportFragment extends VaporFragment {
}
// mount into main container
- if (isTeleportDisabled(props)) {
- if (this.parent) {
- if (!this.mainAnchor) {
- this.mainAnchor = __DEV__
- ? createComment('teleport end')
- : createTextNode()
- }
- if (!this.placeholder) {
- this.placeholder = __DEV__
- ? createComment('teleport start')
- : createTextNode()
- }
- if (!this.mainAnchor.isConnected) {
- insert(this.placeholder, this.parent, this.anchor)
- insert(this.mainAnchor, this.parent, this.anchor)
- }
-
- mount(this.parent, this.mainAnchor)
- }
+ if (isTeleportDisabled(this.props!)) {
+ mount(this.parent, this.mainAnchor!)
}
// mount into target container
else {
- if (isTeleportDeferred(props)) {
+ if (isTeleportDeferred(this.props!)) {
queuePostFlushCb(mountToTarget)
} else {
mountToTarget()
@@ -183,6 +174,17 @@ export class TeleportFragment extends VaporFragment {
}
}
+ insert = (container: ParentNode, anchor: Node | null): void => {
+ // insert anchors in the main view
+ this.placeholder = __DEV__
+ ? createComment('teleport start')
+ : createTextNode()
+ this.mainAnchor = __DEV__ ? createComment('teleport end') : createTextNode()
+ insert(this.placeholder, container, anchor)
+ insert(this.mainAnchor, container, anchor)
+ this.update()
+ }
+
remove = (parent: ParentNode | undefined = this.parent!): void => {
// remove nodes
if (this.nodes) {
diff --git a/packages/runtime-vapor/src/fragment.ts b/packages/runtime-vapor/src/fragment.ts
index f5b70b08b..58f9d9379 100644
--- a/packages/runtime-vapor/src/fragment.ts
+++ b/packages/runtime-vapor/src/fragment.ts
@@ -41,8 +41,6 @@ export class VaporFragment
remove?: (parent?: ParentNode, transitionHooks?: TransitionHooks) => void
fallback?: BlockFn
- target?: ParentNode | null
- targetAnchor?: Node | null
getNodes?: () => Block
setRef?: (comp: VaporComponentInstance) => void