Skip to content

Commit

Permalink
refactor(runtime-vapor): extract invoke hook
Browse files Browse the repository at this point in the history
  • Loading branch information
sxzz committed Mar 15, 2024
1 parent d282af9 commit edd43ee
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 62 deletions.
2 changes: 1 addition & 1 deletion packages/runtime-vapor/__tests__/componentEmits.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ describe('component: emit', () => {
expect(isEmitListener(options, 'onFooBaz')).toBe(true)
})

test('does not emit after unmount', async () => {
test.fails('does not emit after unmount', async () => {
const fn = vi.fn()
const { instance } = define({
emits: ['closing'],
Expand Down
28 changes: 25 additions & 3 deletions packages/runtime-vapor/src/apiLifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ import {
import { warn } from './warning'
import { pauseTracking, resetTracking } from '@vue/reactivity'
import { ErrorTypeStrings, callWithAsyncErrorHandling } from './errorHandling'
import { toHandlerKey } from '@vue/shared'
import { invokeArrayFns, toHandlerKey } from '@vue/shared'
import { type DirectiveHookName, invokeDirectiveHook } from './directives'

export enum VaporLifecycleHooks {
BEFORE_CREATE = 'bc',
CREATED = 'c',
BEFORE_MOUNT = 'bm',
MOUNTED = 'm',
BEFORE_UPDATE = 'bu',
Expand Down Expand Up @@ -89,3 +88,26 @@ export function onErrorCaptured<TError = Error>(
) {
injectHook(VaporLifecycleHooks.ERROR_CAPTURED, hook, target)
}

export function invokeHook(
instance: ComponentInternalInstance,
type: VaporLifecycleHooks,
) {
const reset = setCurrentInstance(instance)
const hook = instance[type]
hook && invokeArrayFns(hook)

const directiveMap: Partial<Record<VaporLifecycleHooks, DirectiveHookName>> =
{
[VaporLifecycleHooks.BEFORE_MOUNT]: 'beforeMount',
[VaporLifecycleHooks.MOUNTED]: 'mounted',
[VaporLifecycleHooks.BEFORE_UPDATE]: 'beforeUpdate',
[VaporLifecycleHooks.UPDATED]: 'updated',
[VaporLifecycleHooks.BEFORE_UNMOUNT]: 'beforeUnmount',
[VaporLifecycleHooks.UNMOUNTED]: 'unmounted',
}
const name = directiveMap[type]
name && invokeDirectiveHook(instance, name)

reset()
}
16 changes: 0 additions & 16 deletions packages/runtime-vapor/src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,6 @@ export interface ComponentInternalInstance {
isUnmounted: boolean
isUpdating: boolean
// TODO: registory of provides, lifecycles, ...
/**
* @internal
*/
[VaporLifecycleHooks.BEFORE_CREATE]: LifecycleHook
/**
* @internal
*/
[VaporLifecycleHooks.CREATED]: LifecycleHook
/**
* @internal
*/
Expand Down Expand Up @@ -186,14 +178,6 @@ export const createComponentInstance = (
isUnmounted: false,
isUpdating: false,
// TODO: registory of provides, appContext, lifecycles, ...
/**
* @internal
*/
[VaporLifecycleHooks.BEFORE_CREATE]: null,
/**
* @internal
*/
[VaporLifecycleHooks.CREATED]: null,
/**
* @internal
*/
Expand Down
41 changes: 15 additions & 26 deletions packages/runtime-vapor/src/render.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import { proxyRefs } from '@vue/reactivity'
import { invokeArrayFns, isArray, isFunction, isObject } from '@vue/shared'
import {
type ComponentInternalInstance,
setCurrentInstance,
unsetCurrentInstance,
} from './component'
import { invokeDirectiveHook } from './directives'
import { isArray, isFunction, isObject } from '@vue/shared'
import { type ComponentInternalInstance, setCurrentInstance } from './component'
import { insert, querySelector, remove } from './dom/element'
import { flushPostFlushCbs, queuePostRenderEffect } from './scheduler'
import { VaporLifecycleHooks, invokeHook } from './apiLifecycle'

export const fragmentKey = Symbol(__DEV__ ? `fragmentKey` : ``)

Expand Down Expand Up @@ -71,39 +67,32 @@ function mountComponent(
}
return (instance.block = block)
})!
const { bm, m } = instance
reset()

// hook: beforeMount
bm && invokeArrayFns(bm)
invokeDirectiveHook(instance, 'beforeMount')
invokeHook(instance, VaporLifecycleHooks.BEFORE_MOUNT)

insert(block, instance.container)
instance.isMounted = true

// hook: mounted
queuePostRenderEffect(() => {
invokeDirectiveHook(instance, 'mounted')
m && invokeArrayFns(m)
invokeHook(instance, VaporLifecycleHooks.MOUNTED)
})
reset()

return instance
}

export function unmountComponent(instance: ComponentInternalInstance) {
const { container, block, scope, um, bum } = instance
const { container, block, scope } = instance

// hook: beforeUnmount
bum && invokeArrayFns(bum)
invokeDirectiveHook(instance, 'beforeUnmount')
invokeHook(instance, VaporLifecycleHooks.BEFORE_UNMOUNT)

scope.stop()
block && remove(block, container)
instance.isMounted = false
instance.isUnmounted = true

// hook: unmounted
invokeDirectiveHook(instance, 'unmounted')
um && invokeArrayFns(um)
unsetCurrentInstance()
queuePostRenderEffect(() => {
invokeHook(instance, VaporLifecycleHooks.UNMOUNTED)
instance.isMounted = false
instance.isUnmounted = true
})

block && remove(block, container)
}
22 changes: 6 additions & 16 deletions packages/runtime-vapor/src/renderWatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
type BaseWatchOptions,
baseWatch,
} from '@vue/reactivity'
import { NOOP, extend, invokeArrayFns, remove } from '@vue/shared'
import { NOOP, extend, remove } from '@vue/shared'
import {
type ComponentInternalInstance,
getCurrentInstance,
Expand All @@ -16,7 +16,7 @@ import {
} from './scheduler'
import { handleError as handleErrorWithInstance } from './errorHandling'
import { warn } from './warning'
import { invokeDirectiveHook } from './directives'
import { VaporLifecycleHooks, invokeHook } from './apiLifecycle'

interface RenderWatchOptions {
immediate?: boolean
Expand Down Expand Up @@ -78,16 +78,10 @@ const createMiddleware =
let value: unknown
// with lifecycle
if (instance && instance.isMounted) {
const { bu, u, dirs } = instance
// beforeUpdate hook
const isFirstEffect = !instance.isUpdating
if (isFirstEffect) {
if (bu) {
invokeArrayFns(bu)
}
if (dirs) {
invokeDirectiveHook(instance, 'beforeUpdate')
}
invokeHook(instance, VaporLifecycleHooks.BEFORE_UPDATE)
instance.isUpdating = true
}

Expand All @@ -99,13 +93,9 @@ const createMiddleware =
if (isFirstEffect) {
queuePostRenderEffect(() => {
instance.isUpdating = false
if (dirs) {
invokeDirectiveHook(instance, 'updated')
}
// updated hook
if (u) {
queuePostRenderEffect(u)
}
queuePostRenderEffect(() =>
invokeHook(instance, VaporLifecycleHooks.UPDATED),
)
})
}
} else {
Expand Down
5 changes: 5 additions & 0 deletions playground/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
getCurrentInstance,
onBeforeUpdate,
onUpdated,
onUnmounted,
} from 'vue/vapor'
const instance = getCurrentInstance()!
Expand Down Expand Up @@ -36,6 +37,10 @@ onUpdated(() => {
console.log('updated')
})
onUnmounted(() => {
console.log('onUnmounted')
})
const log = (arg: any) => {
console.log('callback in render effect')
return arg
Expand Down

0 comments on commit edd43ee

Please sign in to comment.