mirror of https://github.com/vuejs/core.git
wip: refactor
This commit is contained in:
parent
61d6f4801b
commit
dccc47c265
|
@ -73,7 +73,7 @@ export interface KeepAliveContext extends ComponentRenderContext {
|
|||
deactivate: (vnode: VNode) => void
|
||||
}
|
||||
|
||||
export const isKeepAlive = (vnode: VNode): boolean =>
|
||||
export const isKeepAlive = (vnode: any): boolean =>
|
||||
(vnode.type as any).__isKeepAlive
|
||||
|
||||
const KeepAliveImpl: ComponentOptions = {
|
||||
|
@ -478,7 +478,7 @@ function injectToKeepAliveRoot(
|
|||
}, 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
|
||||
|
|
|
@ -564,7 +564,7 @@ export { getComponentName } from './component'
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
export { matches, isKeepAlive } from './components/KeepAlive'
|
||||
export { matches, isKeepAlive, resetShapeFlag } from './components/KeepAlive'
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
|
|
|
@ -9,8 +9,8 @@ import {
|
|||
} 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,
|
||||
|
@ -144,7 +144,7 @@ describe('VaporKeepAlive', () => {
|
|||
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)
|
||||
|
@ -180,7 +180,7 @@ describe('VaporKeepAlive', () => {
|
|||
return createIf(
|
||||
() => toggle.value,
|
||||
() =>
|
||||
createComponent(VaporKeepAlive as any, null, {
|
||||
createComponent(VaporKeepAlive, null, {
|
||||
default: () => createDynamicComponent(() => views[viewRef.value]),
|
||||
}),
|
||||
)
|
||||
|
@ -235,7 +235,7 @@ describe('VaporKeepAlive', () => {
|
|||
return createIf(
|
||||
() => toggle.value,
|
||||
() =>
|
||||
createComponent(VaporKeepAlive as any, null, {
|
||||
createComponent(VaporKeepAlive, null, {
|
||||
default: () => createDynamicComponent(() => views[viewRef.value]),
|
||||
}),
|
||||
)
|
||||
|
@ -295,7 +295,7 @@ describe('VaporKeepAlive', () => {
|
|||
const toggle = ref(true)
|
||||
const { html } = define({
|
||||
setup() {
|
||||
return createComponent(VaporKeepAlive as any, null, {
|
||||
return createComponent(VaporKeepAlive, null, {
|
||||
default() {
|
||||
return createIf(
|
||||
() => toggle.value,
|
||||
|
@ -350,7 +350,7 @@ describe('VaporKeepAlive', () => {
|
|||
const toggle = ref(true)
|
||||
const { html } = define({
|
||||
setup() {
|
||||
return createComponent(VaporKeepAlive as any, null, {
|
||||
return createComponent(VaporKeepAlive, null, {
|
||||
default() {
|
||||
return createIf(
|
||||
() => toggle.value,
|
||||
|
@ -375,7 +375,7 @@ describe('VaporKeepAlive', () => {
|
|||
onActivated(() => oneHooks.activated())
|
||||
onDeactivated(() => oneHooks.deactivated())
|
||||
onUnmounted(() => oneHooks.unmounted())
|
||||
return createComponent(VaporKeepAlive as any, null, {
|
||||
return createComponent(VaporKeepAlive, null, {
|
||||
default() {
|
||||
return createIf(
|
||||
() => toggle2.value,
|
||||
|
@ -389,7 +389,7 @@ describe('VaporKeepAlive', () => {
|
|||
const toggle1 = ref(true)
|
||||
const { html } = define({
|
||||
setup() {
|
||||
return createComponent(VaporKeepAlive as any, null, {
|
||||
return createComponent(VaporKeepAlive, null, {
|
||||
default() {
|
||||
return createIf(
|
||||
() => toggle1.value,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { isArray } from '@vue/shared'
|
||||
import {
|
||||
type VaporComponentInstance,
|
||||
currentInstance,
|
||||
isVaporComponent,
|
||||
mountComponent,
|
||||
unmountComponent,
|
||||
|
@ -8,6 +9,8 @@ import {
|
|||
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
|
||||
|
@ -50,8 +53,14 @@ export class DynamicFragment extends VaporFragment {
|
|||
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)
|
||||
}
|
||||
|
@ -59,6 +68,11 @@ export class DynamicFragment extends VaporFragment {
|
|||
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
|
||||
|
|
|
@ -15,7 +15,6 @@ import {
|
|||
currentInstance,
|
||||
endMeasure,
|
||||
expose,
|
||||
isKeepAlive,
|
||||
nextUid,
|
||||
popWarningContext,
|
||||
pushWarningContext,
|
||||
|
@ -36,7 +35,13 @@ import {
|
|||
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,
|
||||
|
@ -376,6 +381,7 @@ export class VaporComponentInstance implements GenericComponentInstance {
|
|||
propsOptions?: NormalizedPropsOptions
|
||||
emitsOptions?: ObjectEmitsOptions | null
|
||||
isSingleRoot?: boolean
|
||||
shapeFlag?: number
|
||||
|
||||
constructor(
|
||||
comp: VaporComponent,
|
||||
|
@ -498,13 +504,12 @@ export function mountComponent(
|
|||
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
|
||||
}
|
||||
|
@ -516,9 +521,7 @@ export function mountComponent(
|
|||
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!)
|
||||
|
@ -533,13 +536,8 @@ export function unmountComponent(
|
|||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -3,25 +3,25 @@ import {
|
|||
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: (
|
||||
|
@ -30,15 +30,14 @@ export interface KeepAliveInstance extends VaporComponentInstance {
|
|||
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,
|
||||
|
@ -57,7 +56,6 @@ const VaporKeepAliveImpl = defineVaporComponent({
|
|||
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
|
||||
|
@ -90,9 +88,10 @@ const VaporKeepAliveImpl = defineVaporComponent({
|
|||
|
||||
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) {
|
||||
|
@ -104,12 +103,20 @@ const VaporKeepAliveImpl = defineVaporComponent({
|
|||
})
|
||||
})
|
||||
|
||||
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 = (
|
||||
|
@ -117,9 +124,6 @@ const VaporKeepAliveImpl = defineVaporComponent({
|
|||
parentNode: ParentNode,
|
||||
anchor: Node,
|
||||
) => {
|
||||
// invalidateMount(instance.m)
|
||||
// invalidateMount(instance.a)
|
||||
|
||||
const cachedBlock = cache.get(instance.type)!
|
||||
insert((instance.block = cachedBlock.block), parentNode, anchor)
|
||||
queuePostFlushCb(() => {
|
||||
|
@ -144,20 +148,12 @@ const VaporKeepAliveImpl = defineVaporComponent({
|
|||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
Loading…
Reference in New Issue