Skip to content

Latest commit

 

History

History
100 lines (73 loc) · 3.36 KB

002.md

File metadata and controls

100 lines (73 loc) · 3.36 KB

Vue 2 中的 "hook"

创建时间 2021 年 09 月 14 日

在翻阅 Vue 2 文档时,无意中看到示例代码里出现了一个奇怪的 event。链接在这

官方在介绍 $on$once$off 时,列举了一个例子:

mounted: function () {
  var picker = new Pikaday({
    field: this.$refs.input,
    format: 'YYYY-MM-DD'
  })

  this.$once('hook:beforeDestroy', function () {
    picker.destroy()
  })
}

'hook:beforeDestroy' 这玩意是啥,看原文介绍应该是等同于 beforeDestroy 这个生命周期钩子的。

在 Vue 源代码中检索了一下,终于在这里,找到了相对应的定义。

export function callHook(vm: Component, hook: string) {
  // #7573 disable dep collection when invoking lifecycle hooks
  pushTarget()
  const handlers = vm.$options[hook]
  const info = `${hook} hook`
  if (handlers) {
    for (let i = 0, j = handlers.length; i < j; i++) {
      invokeWithErrorHandling(handlers[i], vm, null, vm, info)
    }
  }
  if (vm._hasHookEvent) {
    // 注意这里
    vm.$emit("hook:" + hook)
  }
  popTarget()
}

原来在 Vue 内部中,当生命周期函数被触发时,会同时触发一个以 hook: 开头的事件,而这个事件我们可以在组件内监听到。

这里稍微整理了一下事件的名称:

忽略前面的 hook: 就是正常的 选项生命周期函数

  • hook:beforeUpdate
  • hook:updated
  • hook:beforeCreate
  • hook:created
  • hook:beforeMount
  • hook:mounted
  • hook:beforeDestroy
  • hook:destroyed
  • hook:activated
  • hook:deactivated

用途

知道了这用法后,就可以用来写一些"奇奇怪怪"的代码了。比如官方文档中提到的,可以在注册事件或者第三方库时顺便再把注销相关的逻辑给写上。

mounted(){
  const someEvent = () => {/*...*/}
  window.addEventListener("resize", someEvent)

  this.$once("hook:beforeDestroy", () => {
    window.addEventListener("resize", someEvent)
  })
}

甚至你还可以在父组件监听子组件的生命周期

<Children @hook:mounted="handleChildrenMounted" />

在 Vue 3 中的表现

由于 Vue 3 把 $on $once $off 这三个实例方法移除了(文档传送门)。所以在 Vue 3 中无法使用 this.$once("hook:xxx") 这种方式监听。但是这种方式还是可行。

<Children @hook:mounted="handleChildrenMounted" />

总结

不推荐使用! 不推荐使用! 不推荐使用! 重要的事情说三遍。

特别是在 Vue 3 环境下,Vue 3 提供了更好用的 composition-api。

虽然看起来,有了这一 API 后,我们可以以更细的颗粒度去控制生命周期函数。但是, 正如 @posva 在该 issue中提到的:这并不是一个公共的 API。所以我们才没有在文档中找到相关的介绍。而这种没有明确在文档中提到的用法,我们在使用上要慎之又慎。因为我们无法得知是否在后续的某次更新中,Vue 会把这种用法给替代掉。