Skip to content

Commit 0a7d56d

Browse files
committed
wip: vdom interop
1 parent 05f197d commit 0a7d56d

File tree

6 files changed

+117
-39
lines changed

6 files changed

+117
-39
lines changed

packages/runtime-core/src/apiCreateApp.ts

+7
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,13 @@ export interface VaporInteropInterface {
193193
unmount(vnode: VNode, doRemove?: boolean): void
194194
move(vnode: VNode, container: any, anchor: any): void
195195
slot(n1: VNode | null, n2: VNode, container: any, anchor: any): void
196+
activate(
197+
vnode: VNode,
198+
container: any,
199+
anchor: any,
200+
parentComponent: ComponentInternalInstance,
201+
): void
202+
deactivate(vnode: VNode, container: any): void
196203

197204
vdomMount: (component: ConcreteComponent, props?: any, slots?: any) => any
198205
vdomUnmount: UnmountComponentFn

packages/runtime-core/src/components/KeepAlive.ts

+10
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ export interface KeepAliveContext extends ComponentRenderContext {
7272
optimized: boolean,
7373
) => void
7474
deactivate: (vnode: VNode) => void
75+
getCachedComponent: (vnode: VNode) => VNode
76+
getStorageContainer: () => RendererElement
7577
}
7678

7779
export const isKeepAlive = (vnode: any): boolean =>
@@ -126,6 +128,14 @@ const KeepAliveImpl: ComponentOptions = {
126128
} = renderer
127129
const storageContainer = createElement('div')
128130

131+
sharedContext.getStorageContainer = () => storageContainer
132+
133+
sharedContext.getCachedComponent = (vnode: VNode) => {
134+
const key =
135+
vnode.key == null ? (vnode.type as ConcreteComponent) : vnode.key
136+
return cache.get(key)!
137+
}
138+
129139
sharedContext.activate = (
130140
vnode,
131141
container,

packages/runtime-core/src/renderer.ts

+28-10
Original file line numberDiff line numberDiff line change
@@ -1164,12 +1164,21 @@ function baseCreateRenderer(
11641164

11651165
if ((n2.type as ConcreteComponent).__vapor) {
11661166
if (n1 == null) {
1167-
getVaporInterface(parentComponent, n2).mount(
1168-
n2,
1169-
container,
1170-
anchor,
1171-
parentComponent,
1172-
)
1167+
if (n2.shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE) {
1168+
getVaporInterface(parentComponent, n2).activate(
1169+
n2,
1170+
container,
1171+
anchor,
1172+
parentComponent!,
1173+
)
1174+
} else {
1175+
getVaporInterface(parentComponent, n2).mount(
1176+
n2,
1177+
container,
1178+
anchor,
1179+
parentComponent,
1180+
)
1181+
}
11731182
} else {
11741183
getVaporInterface(parentComponent, n2).update(
11751184
n1,
@@ -2178,7 +2187,14 @@ function baseCreateRenderer(
21782187
}
21792188

21802189
if (shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
2181-
;(parentComponent!.ctx as KeepAliveContext).deactivate(vnode)
2190+
if ((vnode.type as ConcreteComponent).__vapor) {
2191+
getVaporInterface(parentComponent!, vnode).deactivate(
2192+
vnode,
2193+
(parentComponent!.ctx as KeepAliveContext).getStorageContainer(),
2194+
)
2195+
} else {
2196+
;(parentComponent!.ctx as KeepAliveContext).deactivate(vnode)
2197+
}
21822198
return
21832199
}
21842200

@@ -2425,7 +2441,7 @@ function baseCreateRenderer(
24252441
const getNextHostNode: NextFn = vnode => {
24262442
if (vnode.shapeFlag & ShapeFlags.COMPONENT) {
24272443
if ((vnode.type as ConcreteComponent).__vapor) {
2428-
return hostNextSibling((vnode.component! as any).block)
2444+
return hostNextSibling(vnode.anchor!)
24292445
}
24302446
return getNextHostNode(vnode.component!.subTree)
24312447
}
@@ -2620,9 +2636,11 @@ export function traverseStaticChildren(
26202636
}
26212637

26222638
function locateNonHydratedAsyncRoot(
2623-
instance: ComponentInternalInstance,
2639+
instance: GenericComponentInstance,
26242640
): ComponentInternalInstance | undefined {
2625-
const subComponent = instance.subTree.component
2641+
const subComponent = instance.vapor
2642+
? null
2643+
: (instance as ComponentInternalInstance).subTree.component
26262644
if (subComponent) {
26272645
if (subComponent.asyncDep && !subComponent.asyncResolved) {
26282646
return subComponent

packages/runtime-vapor/src/component.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,11 @@ export function createComponent(
153153
}
154154

155155
// try to get the cached instance if inside keep-alive
156-
if (currentInstance && isKeepAlive(currentInstance)) {
156+
if (
157+
currentInstance &&
158+
currentInstance.vapor &&
159+
isKeepAlive(currentInstance)
160+
) {
157161
const cached = (currentInstance as KeepAliveInstance).getCachedComponent(
158162
component,
159163
)
@@ -167,9 +171,11 @@ export function createComponent(
167171
rawProps,
168172
rawSlots,
169173
)
170-
if (!isHydrating && _insertionParent) {
171-
insert(frag, _insertionParent, _insertionAnchor)
172-
}
174+
// TODO: problem is `frag.insert` will be called multiple times
175+
// if used in v-if
176+
// if (!isHydrating && _insertionParent) {
177+
// insert(frag, _insertionParent, _insertionAnchor)
178+
// }
173179
return frag
174180
}
175181

packages/runtime-vapor/src/components/KeepAlive.ts

+35-20
Original file line numberDiff line numberDiff line change
@@ -147,29 +147,11 @@ export const VaporKeepAliveImpl: ObjectVaporComponent = defineVaporComponent({
147147

148148
keepAliveInstance.activate = (instance, parentNode, anchor) => {
149149
current = instance
150-
insert(instance.block, parentNode, anchor)
151-
152-
queuePostFlushCb(() => {
153-
instance.isDeactivated = false
154-
if (instance.a) invokeArrayFns(instance.a)
155-
})
156-
157-
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
158-
devtoolsComponentAdded(instance)
159-
}
150+
activate(instance, parentNode, anchor)
160151
}
161152

162153
keepAliveInstance.deactivate = instance => {
163-
insert(instance.block, storageContainer)
164-
165-
queuePostFlushCb(() => {
166-
if (instance.da) invokeArrayFns(instance.da)
167-
instance.isDeactivated = true
168-
})
169-
170-
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
171-
devtoolsComponentAdded(instance)
172-
}
154+
deactivate(instance, storageContainer)
173155
}
174156

175157
let children = slots.default()
@@ -248,3 +230,36 @@ function getInnerComponent(block: Block): VaporComponentInstance | undefined {
248230
function isVdomInteropFragment(block: Block): block is VaporFragment {
249231
return !!(isFragment(block) && block.insert)
250232
}
233+
234+
export function activate(
235+
instance: VaporComponentInstance,
236+
parentNode: ParentNode,
237+
anchor?: Node | null | 0,
238+
): void {
239+
insert(instance.block, parentNode, anchor)
240+
241+
queuePostFlushCb(() => {
242+
instance.isDeactivated = false
243+
if (instance.a) invokeArrayFns(instance.a)
244+
})
245+
246+
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
247+
devtoolsComponentAdded(instance)
248+
}
249+
}
250+
251+
export function deactivate(
252+
instance: VaporComponentInstance,
253+
container: ParentNode,
254+
): void {
255+
insert(instance.block, container)
256+
257+
queuePostFlushCb(() => {
258+
if (instance.da) invokeArrayFns(instance.da)
259+
instance.isDeactivated = true
260+
})
261+
262+
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
263+
devtoolsComponentAdded(instance)
264+
}
265+
}

packages/runtime-vapor/src/vdomInterop.ts

+27-5
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ import {
99
type Slots,
1010
type VNode,
1111
type VaporInteropInterface,
12-
activate,
1312
createVNode,
1413
currentInstance,
15-
deactivate,
1614
ensureRenderer,
1715
onScopeDispose,
1816
renderSlot,
1917
shallowRef,
2018
simpleSetCurrentInstance,
19+
activate as vdomActivate,
20+
deactivate as vdomDeactivate,
2121
} from '@vue/runtime-dom'
2222
import {
2323
type LooseRawProps,
@@ -35,7 +35,12 @@ import type { RawSlots, VaporSlot } from './componentSlots'
3535
import { renderEffect } from './renderEffect'
3636
import { createTextNode } from './dom/node'
3737
import { optimizePropertyLookup } from './dom/prop'
38-
import type { KeepAliveInstance } from './components/KeepAlive'
38+
import {
39+
type KeepAliveInstance,
40+
activate,
41+
deactivate,
42+
} from './components/KeepAlive'
43+
import type { KeepAliveContext } from 'packages/runtime-core/src/components/KeepAlive'
3944

4045
// mounting vapor components and slots in vdom
4146
const vaporInteropImpl: Omit<
@@ -116,6 +121,23 @@ const vaporInteropImpl: Omit<
116121
insert(vnode.vb || (vnode.component as any), container, anchor)
117122
insert(vnode.anchor as any, container, anchor)
118123
},
124+
125+
activate(vnode, container, anchor, parentComponent) {
126+
const cached = (parentComponent.ctx as KeepAliveContext).getCachedComponent(
127+
vnode,
128+
)
129+
130+
vnode.el = cached.el
131+
vnode.component = cached.component
132+
vnode.anchor = cached.anchor
133+
activate(vnode.component as any, container, anchor)
134+
insert(vnode.anchor as any, container, anchor)
135+
},
136+
137+
deactivate(vnode, container) {
138+
deactivate(vnode.component as any, container)
139+
insert(vnode.anchor as any, container)
140+
},
119141
}
120142

121143
const vaporSlotPropsProxyHandler: ProxyHandler<
@@ -176,7 +198,7 @@ function createVDOMComponent(
176198
const parentInstance = currentInstance as VaporComponentInstance
177199
const unmount = (parentNode?: ParentNode) => {
178200
if (vnode.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
179-
deactivate(
201+
vdomDeactivate(
180202
vnode,
181203
(parentInstance as KeepAliveInstance).getStorageContainer(),
182204
internals,
@@ -190,7 +212,7 @@ function createVDOMComponent(
190212

191213
frag.insert = (parentNode, anchor) => {
192214
if (vnode.shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE) {
193-
activate(
215+
vdomActivate(
194216
vnode,
195217
parentNode,
196218
anchor,

0 commit comments

Comments
 (0)