[Vue 源码] Vue 3.2 - 生命周期

388 阅读1分钟

代码运行结果

provide.gif

代码示例

    <div id="app"></div>
    <script>
      let {
        createApp,
        reactive,
        Fragment,
        toRefs,
        h,
        getCurrentInstance,
        provide,
        inject,
        onMounted
      } = Vue

      const MyCpn = {
        setup(props, { emit, slots }) {
          const state = inject('state')
          return () => h('div', null, [state.count])
        }
      }

      const App = {
        setup() {
          const state = reactive({ count: 0 })
          provide('state', state)

          onMounted(() => {
            setTimeout(() => {
              state.count++
            }, 2000)
          })
        },

        render() {
          return h(MyCpn, null)
        }
      }

      createApp(App).mount('#app')
    </script>

第一:调用 onMounted 生命周期函数,实际上是调用了 createHook 函数,并通过枚举类型,传入生命周期的 type。

export const onBeforeMount = createHook(LifecycleHooks.BEFORE_MOUNT)
export const onMounted = createHook(LifecycleHooks.MOUNTED)
export const onBeforeUpdate = createHook(LifecycleHooks.BEFORE_UPDATE)
export const onUpdated = createHook(LifecycleHooks.UPDATED)
export const onBeforeUnmount = createHook(LifecycleHooks.BEFORE_UNMOUNT)
export const onUnmounted = createHook(LifecycleHooks.UNMOUNTED)
export const onServerPrefetch = createHook(LifecycleHooks.SERVER_PREFETCH)

生命周期 枚举类型的 type, 就是首字母的缩写

export const enum LifecycleHooks {
  BEFORE_CREATE = 'bc',
  CREATED = 'c',
  BEFORE_MOUNT = 'bm',
  MOUNTED = 'm',
  BEFORE_UPDATE = 'bu',
  UPDATED = 'u',
  BEFORE_UNMOUNT = 'bum',
  UNMOUNTED = 'um',
  DEACTIVATED = 'da',
  ACTIVATED = 'a',
  RENDER_TRIGGERED = 'rtg',
  RENDER_TRACKED = 'rtc',
  ERROR_CAPTURED = 'ec',
  SERVER_PREFETCH = 'sp'
}

第二:在 createHook 函数中,返回生命周期钩子函数,我们组件当中调用的生命周期函数就是 createHook 返回的这个函数。

export const createHook =
  <T extends Function = () => any>(lifecycle: LifecycleHooks) =>
  (hook: T, target: ComponentInternalInstance | null = currentInstance) =>
    // post-create lifecycle registrations are noops during SSR (except for serverPrefetch)
    (!isInSSRComponentSetup || lifecycle === LifecycleHooks.SERVER_PREFETCH) &&
    injectHook(lifecycle, (...args: unknown[]) => hook(...args), target)

第三:传入钩子 hook 和 当前组件实例,调用 injectHook 函数。

第四:在 injectHook 函数中,将生命周期函数,加入到组件实例对应的生命周期队列当中去。

lifeCycle.gif

{
 m: [() => {}, () => {}],
 u: [() => {}, () => {}]
}
export function injectHook(
  type: LifecycleHooks,
  hook: Function & { __weh?: Function },
  target: ComponentInternalInstance | null = currentInstance,
  prepend: boolean = false
): Function | undefined {
  if (target) {
    const hooks = target[type] || (target[type] = [])
    // cache the error handling wrapper for injected hooks so the same hook
    if (prepend) {
      hooks.unshift(wrappedHook)
    } else {
      hooks.push(wrappedHook)
    }
    return wrappedHook
  }
}

最后就是将这些生命周期的钩子函数,在组件挂载和更新的阶段进行调用了。