deactivate: (vnode: VNode) => void
}
-export const isKeepAlive = (vnode: VNode): boolean =>
+export const isKeepAlive = (vnode: any): boolean =>
(vnode.type as any).__isKeepAlive
const KeepAliveImpl: ComponentOptions = {
}, target)
}
-function resetShapeFlag(vnode: VNode) {
+export function resetShapeFlag(vnode: any): void {
// bitwise operations to remove keep alive flags
vnode.shapeFlag &= ~ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE
vnode.shapeFlag &= ~ShapeFlags.COMPONENT_KEPT_ALIVE
/**
* @internal
*/
-export { matches, isKeepAlive } from './components/KeepAlive'
+export { matches, isKeepAlive, resetShapeFlag } from './components/KeepAlive'
/**
* @internal
*/
} from 'vue'
import type { VaporComponent } from '../../src/component'
import { makeRender } from '../_utils'
+import { VaporKeepAliveImpl as VaporKeepAlive } from '../../src/components/KeepAlive'
import {
- VaporKeepAlive,
child,
createComponent,
createDynamicComponent,
const { mount } = define({
setup() {
const setTemplateRef = createTemplateRefSetter()
- const n4 = createComponent(VaporKeepAlive as any, null, {
+ const n4 = createComponent(VaporKeepAlive, null, {
default: () => {
const n0 = createDynamicComponent(() => views[viewRef.value]) as any
setTemplateRef(n0, instanceRef)
return createIf(
() => toggle.value,
() =>
- createComponent(VaporKeepAlive as any, null, {
+ createComponent(VaporKeepAlive, null, {
default: () => createDynamicComponent(() => views[viewRef.value]),
}),
)
return createIf(
() => toggle.value,
() =>
- createComponent(VaporKeepAlive as any, null, {
+ createComponent(VaporKeepAlive, null, {
default: () => createDynamicComponent(() => views[viewRef.value]),
}),
)
const toggle = ref(true)
const { html } = define({
setup() {
- return createComponent(VaporKeepAlive as any, null, {
+ return createComponent(VaporKeepAlive, null, {
default() {
return createIf(
() => toggle.value,
const toggle = ref(true)
const { html } = define({
setup() {
- return createComponent(VaporKeepAlive as any, null, {
+ return createComponent(VaporKeepAlive, null, {
default() {
return createIf(
() => toggle.value,
onActivated(() => oneHooks.activated())
onDeactivated(() => oneHooks.deactivated())
onUnmounted(() => oneHooks.unmounted())
- return createComponent(VaporKeepAlive as any, null, {
+ return createComponent(VaporKeepAlive, null, {
default() {
return createIf(
() => toggle2.value,
const toggle1 = ref(true)
const { html } = define({
setup() {
- return createComponent(VaporKeepAlive as any, null, {
+ return createComponent(VaporKeepAlive, null, {
default() {
return createIf(
() => toggle1.value,
import { isArray } from '@vue/shared'
import {
type VaporComponentInstance,
+ currentInstance,
isVaporComponent,
mountComponent,
unmountComponent,
import { createComment, createTextNode } from './dom/node'
import { EffectScope, pauseTracking, resetTracking } from '@vue/reactivity'
import { isHydrating } from './dom/hydration'
+import { isKeepAlive } from 'vue'
+import type { KeepAliveInstance } from './components/KeepAlive'
export type Block =
| Node
pauseTracking()
const parent = this.anchor.parentNode
+ const instance = currentInstance!
// teardown previous branch
if (this.scope) {
+ if (isKeepAlive(instance)) {
+ ;(instance as KeepAliveInstance).process(
+ this.nodes as VaporComponentInstance,
+ )
+ }
this.scope.stop()
parent && remove(this.nodes, parent)
}
if (render) {
this.scope = new EffectScope()
this.nodes = this.scope.run(render) || []
+ if (isKeepAlive(instance)) {
+ ;(instance as KeepAliveInstance).process(
+ this.nodes as VaporComponentInstance,
+ )
+ }
if (parent) insert(this.nodes, parent, this.anchor)
} else {
this.scope = undefined
currentInstance,
endMeasure,
expose,
- isKeepAlive,
nextUid,
popWarningContext,
pushWarningContext,
resetTracking,
unref,
} from '@vue/reactivity'
-import { EMPTY_OBJ, invokeArrayFns, isFunction, isString } from '@vue/shared'
+import {
+ EMPTY_OBJ,
+ ShapeFlags,
+ invokeArrayFns,
+ isFunction,
+ isString,
+} from '@vue/shared'
import {
type DynamicPropsSource,
type RawProps,
propsOptions?: NormalizedPropsOptions
emitsOptions?: ObjectEmitsOptions | null
isSingleRoot?: boolean
+ shapeFlag?: number
constructor(
comp: VaporComponent,
parentNode: ParentNode,
anchor?: Node | null | 0,
): void {
- let parent
- if (
- (parent = instance.parent) &&
- isKeepAlive(parent as any) &&
- (parent as KeepAliveInstance).isKeptAlive(instance)
- ) {
- ;(parent as KeepAliveInstance).activate(instance, parentNode, anchor as any)
+ if (instance.shapeFlag! & ShapeFlags.COMPONENT_KEPT_ALIVE) {
+ ;(instance.parent as KeepAliveInstance).activate(
+ instance,
+ parentNode,
+ anchor as any,
+ )
instance.isMounted = true
return
}
insert(instance.block, parentNode, anchor)
if (instance.m) queuePostFlushCb(() => invokeArrayFns(instance.m!))
if (
- parent &&
- isKeepAlive(parent as any) &&
- (parent as KeepAliveInstance).shouldKeepAlive(instance) &&
+ instance.shapeFlag! & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE &&
instance.a
) {
queuePostFlushCb(instance.a!)
instance: VaporComponentInstance,
parentNode?: ParentNode,
): void {
- let parent
- if (
- (parent = instance.parent) &&
- isKeepAlive(parent as any) &&
- (parent as KeepAliveInstance).shouldKeepAlive(instance)
- ) {
- ;(parent as KeepAliveInstance).deactivate(instance)
+ if (instance.shapeFlag! & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
+ ;(instance.parent as KeepAliveInstance).deactivate(instance)
return
}
currentInstance,
devtoolsComponentAdded,
getComponentName,
- invalidateMount,
- isKeepAlive,
matches,
onBeforeUnmount,
onMounted,
onUpdated,
queuePostFlushCb,
+ resetShapeFlag,
warn,
watch,
} from '@vue/runtime-dom'
import { type Block, insert, isFragment, isValidBlock } from '../block'
import {
+ type ObjectVaporComponent,
type VaporComponent,
type VaporComponentInstance,
isVaporComponent,
unmountComponent,
} from '../component'
import { defineVaporComponent } from '../apiDefineComponent'
-import { invokeArrayFns, isArray } from '@vue/shared'
+import { ShapeFlags, invokeArrayFns, isArray } from '@vue/shared'
export interface KeepAliveInstance extends VaporComponentInstance {
activate: (
anchor: Node,
) => void
deactivate: (instance: VaporComponentInstance) => void
- shouldKeepAlive: (instance: VaporComponentInstance) => boolean
- isKeptAlive: (instance: VaporComponentInstance) => boolean
+ process: (instance: VaporComponentInstance) => void
}
type CacheKey = PropertyKey | VaporComponent
type Cache = Map<CacheKey, VaporComponentInstance>
type Keys = Set<CacheKey>
-const VaporKeepAliveImpl = defineVaporComponent({
+export const VaporKeepAliveImpl: ObjectVaporComponent = defineVaporComponent({
name: 'VaporKeepAlive',
// @ts-expect-error
__isKeepAlive: true,
const keys: Keys = new Set()
const storageContainer = document.createElement('div')
let current: VaporComponentInstance | undefined
- let isUnmounting = false
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
;(keepAliveInstance as any).__v_cache = cache
onMounted(cacheBlock)
onUpdated(cacheBlock)
+
onBeforeUnmount(() => {
- isUnmounting = true
cache.forEach(cached => {
+ resetShapeFlag(cached)
cache.delete(cached.type)
// current instance will be unmounted as part of keep-alive's unmount
if (current && current.type === cached.type) {
})
})
- const children = slots.default()
- if (isArray(children) && children.length > 1) {
- if (__DEV__) {
- warn(`KeepAlive should contain exactly one component child.`)
+ keepAliveInstance.process = (instance: VaporComponentInstance) => {
+ if (cache.has(instance.type)) {
+ instance.shapeFlag! |= ShapeFlags.COMPONENT_KEPT_ALIVE
+ }
+
+ const name = getComponentName(instance.type)
+ if (
+ !(
+ (include && (!name || !matches(include, name))) ||
+ (exclude && name && matches(exclude, name))
+ )
+ ) {
+ instance.shapeFlag! |= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE
}
- return children
}
keepAliveInstance.activate = (
parentNode: ParentNode,
anchor: Node,
) => {
- // invalidateMount(instance.m)
- // invalidateMount(instance.a)
-
const cachedBlock = cache.get(instance.type)!
insert((instance.block = cachedBlock.block), parentNode, anchor)
queuePostFlushCb(() => {
}
}
- keepAliveInstance.shouldKeepAlive = (instance: VaporComponentInstance) => {
- if (isUnmounting) return false
- const name = getComponentName(instance.type)
- if (
- (include && (!name || !matches(include, name))) ||
- (exclude && name && matches(exclude, name))
- ) {
- return false
+ const children = slots.default()
+ if (isArray(children) && children.length > 1) {
+ if (__DEV__) {
+ warn(`KeepAlive should contain exactly one component child.`)
}
- return true
- }
-
- keepAliveInstance.isKeptAlive = (instance: VaporComponentInstance) => {
- return cache.has(instance.type)
+ return children
}
function pruneCache(filter: (name: string) => boolean) {