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 * indicates vapor component
*/ */
__vapor?: boolean __vapor?: boolean
/**
* indicates keep-alive component
*/
__isKeepAlive?: boolean
/** /**
* @internal * @internal
*/ */

View File

@ -456,7 +456,7 @@ function registerKeepAliveHook(
let current = target.parent let current = target.parent
while (current && current.parent) { while (current && current.parent) {
let parent = 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) injectToKeepAliveRoot(wrappedHook, type, target, current)
} }
current = current.parent current = current.parent

View File

@ -50,11 +50,7 @@ export function setRef(
if (!instance || instance.isUnmounted) return if (!instance || instance.isUnmounted) return
const setupState: any = __DEV__ ? instance.setupState || {} : null const setupState: any = __DEV__ ? instance.setupState || {} : null
const refValue = isVaporComponent(el) const refValue = getRefValue(el)
? getExposed(el) || el
: el instanceof DynamicFragment
? getExposed(el.nodes as VaporComponentInstance) || el.nodes
: el
const refs = const refs =
instance.refs === EMPTY_OBJ ? (instance.refs = {}) : instance.refs instance.refs === EMPTY_OBJ ? (instance.refs = {}) : instance.refs
@ -147,3 +143,12 @@ export function setRef(
} }
return ref 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() locateHydrationNode()
} }
// try to get the cached instance if inside keep-alive
if (currentInstance && isKeepAlive(currentInstance)) { if (currentInstance && isKeepAlive(currentInstance)) {
const cache = (currentInstance as KeepAliveInstance).getCache(component) const cached = (currentInstance as KeepAliveInstance).getCachedInstance(
if (cache) return cache component,
)
if (cached) return cached
} }
// vdom interop enabled and component is not an explicit vapor component // vdom interop enabled and component is not an explicit vapor component
@ -525,7 +528,7 @@ export function mountComponent(
} }
if (instance.bm) invokeArrayFns(instance.bm) if (instance.bm) invokeArrayFns(instance.bm)
insert(instance.block, parentNode, anchor) insert(instance.block, parentNode, anchor)
if (instance.m) queuePostFlushCb(() => invokeArrayFns(instance.m!)) if (instance.m) queuePostFlushCb(instance.m!)
if ( if (
instance.shapeFlag! & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE && instance.shapeFlag! & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE &&
instance.a instance.a
@ -558,7 +561,7 @@ export function unmountComponent(
instance.scope.stop() instance.scope.stop()
if (instance.um) { if (instance.um) {
queuePostFlushCb(() => invokeArrayFns(instance.um!)) queuePostFlushCb(instance.um!)
} }
instance.isUnmounted = true instance.isUnmounted = true
} }

View File

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