Skip to content

生命周期钩子(基础组件系统开始)

让我们实现生命周期钩子

实现生命周期钩子非常简单. 你只需要在 ComponentInternalInstance 中注册函数,并在渲染期间的指定时机执行它们. API 本身将在 runtime-core/apiLifecycle.ts 中实现.

需要注意的一点是,你需要考虑 onMounted/onUnmounted/onUpdated 的调度. 注册的函数应该在挂载,卸载和更新完全完成后执行.

因此,我们将在调度器中实现一种名为"post"的新队列类型.这是在现有队列刷新完成后才会被刷新的队列. 图像 ↓

ts
const queue: SchedulerJob[] = [] // 现有实现
const pendingPostFlushCbs: SchedulerJob[] = [] // 这次要创建的新队列

function queueFlush() {
  queue.forEach(job => job())
  flushPostFlushCbs() // 在队列刷新后刷新
}

同时,通过这个,让我们实现一个入队到 pendingPostFlushCbs 的 API. 并且让我们使用它将渲染器中的 effect 入队到 pendingPostFlushCbs.

这次要支持的生命周期钩子:

  • onMounted
  • onUpdated
  • onUnmounted
  • onBeforeMount
  • onBeforeUpdate
  • onBeforeUnmount

让我们实现它,目标是使以下代码工作!

ts
import {
  createApp,
  h,
  onBeforeMount,
  onBeforeUnmount,
  onBeforeUpdate,
  onMounted,
  onUnmounted,
  onUpdated,
  ref,
} from 'chibivue'

const Child = {
  setup() {
    const count = ref(0)
    onBeforeMount(() => {
      console.log('onBeforeMount')
    })

    onUnmounted(() => {
      console.log('onUnmounted')
    })

    onBeforeUnmount(() => {
      console.log('onBeforeUnmount')
    })

    onBeforeUpdate(() => {
      console.log('onBeforeUpdate')
    })

    onUpdated(() => {
      console.log('onUpdated')
    })

    onMounted(() => {
      console.log('onMounted')
    })

    return () =>
      h('div', {}, [
        h('p', {}, [`${count.value}`]),
        h('button', { onClick: () => count.value++ }, ['increment']),
      ])
  },
}

const app = createApp({
  setup() {
    const mountFlag = ref(true)

    return () =>
      h('div', {}, [
        h('button', { onClick: () => (mountFlag.value = !mountFlag.value) }, [
          'toggle',
        ]),
        mountFlag.value ? h(Child, {}, []) : h('p', {}, ['unmounted']),
      ])
  },
})

app.mount('#app')

到此为止的源代码:
chibivue (GitHub)

基于 MIT 许可证发布。