chore: refactor

This commit is contained in:
daiwei 2025-04-10 15:16:35 +08:00
parent 032f46f23c
commit e012bc5c50
5 changed files with 45 additions and 38 deletions

View File

@ -196,6 +196,10 @@ export interface ComponentInternalOptions {
* indicates vapor component
*/
__vapor?: boolean
/**
* indicates keep-alive component
*/
__isKeepAlive?: boolean
/**
* @internal
*/

View File

@ -456,7 +456,7 @@ function registerKeepAliveHook(
let current = target.parent
while (current && current.parent) {
let parent = current.parent
if (isKeepAlive(parent.vapor ? (parent as any) : parent.vnode)) {
if (isKeepAlive(parent.vapor ? parent : parent.vnode)) {
injectToKeepAliveRoot(wrappedHook, type, target, current)
}
current = current.parent

View File

@ -50,11 +50,7 @@ export function setRef(
if (!instance || instance.isUnmounted) return
const setupState: any = __DEV__ ? instance.setupState || {} : null
const refValue = isVaporComponent(el)
? getExposed(el) || el
: el instanceof DynamicFragment
? getExposed(el.nodes as VaporComponentInstance) || el.nodes
: el
const refValue = getRefValue(el)
const refs =
instance.refs === EMPTY_OBJ ? (instance.refs = {}) : instance.refs
@ -147,3 +143,12 @@ export function setRef(
}
return ref
}
const getRefValue = (el: RefEl) => {
if (isVaporComponent(el)) {
return getExposed(el) || el
} else if (el instanceof DynamicFragment) {
return getRefValue(el.nodes as RefEl)
}
return el
}

View File

@ -152,9 +152,12 @@ export function createComponent(
locateHydrationNode()
}
// try to get the cached instance if inside keep-alive
if (currentInstance && isKeepAlive(currentInstance)) {
const cache = (currentInstance as KeepAliveInstance).getCache(component)
if (cache) return cache
const cached = (currentInstance as KeepAliveInstance).getCachedInstance(
component,
)
if (cached) return cached
}
// vdom interop enabled and component is not an explicit vapor component
@ -525,7 +528,7 @@ export function mountComponent(
}
if (instance.bm) invokeArrayFns(instance.bm)
insert(instance.block, parentNode, anchor)
if (instance.m) queuePostFlushCb(() => invokeArrayFns(instance.m!))
if (instance.m) queuePostFlushCb(instance.m!)
if (
instance.shapeFlag! & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE &&
instance.a
@ -558,7 +561,7 @@ export function unmountComponent(
instance.scope.stop()
if (instance.um) {
queuePostFlushCb(() => invokeArrayFns(instance.um!))
queuePostFlushCb(instance.um!)
}
instance.isUnmounted = true
}

View File

@ -12,13 +12,7 @@ import {
warn,
watch,
} from '@vue/runtime-dom'
import {
type Block,
DynamicFragment,
insert,
isFragment,
isValidBlock,
} from '../block'
import { type Block, insert, isFragment } from '../block'
import {
type ObjectVaporComponent,
type VaporComponent,
@ -37,16 +31,17 @@ export interface KeepAliveInstance extends VaporComponentInstance {
) => void
deactivate: (instance: VaporComponentInstance) => void
process: (instance: VaporComponentInstance) => void
getCache: (comp: VaporComponent) => VaporComponentInstance | undefined
getCachedInstance: (
comp: VaporComponent,
) => VaporComponentInstance | undefined
}
type CacheKey = PropertyKey | VaporComponent
type CacheKey = VaporComponent
type Cache = Map<CacheKey, VaporComponentInstance>
type Keys = Set<CacheKey>
export const VaporKeepAliveImpl: ObjectVaporComponent = defineVaporComponent({
name: 'VaporKeepAlive',
// @ts-expect-error
__isKeepAlive: true,
props: {
include: [String, RegExp, Array],
@ -80,13 +75,10 @@ export const VaporKeepAliveImpl: ObjectVaporComponent = defineVaporComponent({
function cacheBlock() {
const { max } = props
// TODO suspense
const currentBlock = keepAliveInstance.block!
if (!isValidBlock(currentBlock)) return
const innerBlock = getInnerBlock(keepAliveInstance.block!)!
if (!innerBlock || !shouldCache(innerBlock)) return
const block = getInnerBlock(currentBlock)!
if (!block || !shouldCache(block)) return
const key = block.type
const key = innerBlock.type
if (cache.has(key)) {
// make this key the freshest
keys.delete(key)
@ -98,7 +90,7 @@ export const VaporKeepAliveImpl: ObjectVaporComponent = defineVaporComponent({
pruneCacheEntry(keys.values().next().value!)
}
}
cache.set(key, (current = block))
cache.set(key, (current = innerBlock))
}
onMounted(cacheBlock)
@ -118,9 +110,12 @@ export const VaporKeepAliveImpl: ObjectVaporComponent = defineVaporComponent({
})
})
keepAliveInstance.getCache = (comp: VaporComponent) => cache.get(comp)
keepAliveInstance.getCachedInstance = (comp: VaporComponent) =>
cache.get(comp)
keepAliveInstance.process = (instance: VaporComponentInstance) => {
const process = (keepAliveInstance.process = (
instance: VaporComponentInstance,
) => {
if (cache.has(instance.type)) {
instance.shapeFlag! |= ShapeFlags.COMPONENT_KEPT_ALIVE
}
@ -128,15 +123,15 @@ export const VaporKeepAliveImpl: ObjectVaporComponent = defineVaporComponent({
if (shouldCache(instance)) {
instance.shapeFlag! |= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE
}
}
})
keepAliveInstance.activate = (
instance: VaporComponentInstance,
parentNode: ParentNode,
anchor: Node,
) => {
const cachedBlock = (current = cache.get(instance.type)!)
insert((instance.block = cachedBlock.block), parentNode, anchor)
current = instance
insert(instance.block, parentNode, anchor)
queuePostFlushCb(() => {
instance.isDeactivated = false
if (instance.a) invokeArrayFns(instance.a)
@ -167,12 +162,11 @@ export const VaporKeepAliveImpl: ObjectVaporComponent = defineVaporComponent({
return children
}
// wrap children in dynamic fragment
if (!isFragment(children)) {
const frag = new DynamicFragment()
frag.update(() => children)
children = frag
}
// `children` could be either a `VaporComponentInstance` or a `DynamicFragment`
// (when using `v-if` or `<component is/>`). For `DynamicFragment` children,
// the `shapeFlag` is processed in `DynamicFragment.update`. Here only need
// to process the `VaporComponentInstance`
if (isVaporComponent(children)) process(children)
function pruneCache(filter: (name: string) => boolean) {
cache.forEach((instance, key) => {
@ -187,6 +181,7 @@ export const VaporKeepAliveImpl: ObjectVaporComponent = defineVaporComponent({
const cached = cache.get(key)
if (cached) {
resetShapeFlag(cached)
// don't unmount if the instance is the current one
if (cached !== current) {
unmountComponent(cached)
}