1. 程式人生 > 其它 >最佳實踐:vue2 父元件監聽子元件生命週期鉤子

最佳實踐:vue2 父元件監聽子元件生命週期鉤子

技術標籤:VuevueHookEvent父元件監聽子元件生命週期鉤子hooksvue最佳實踐

HookEvent

原始碼地址:https://github.com/vuejs/vue/blob/master/src/core/instance/lifecycle.js#L314

export function callHook (vm: Component, hook: string) {
  const handlers = vm.$options[hook]
  if (handlers) {
    for (let i = 0, j = handlers.length; i < j; i++)
{ try { handlers[i].call(vm) } catch (e) { handleError(e, vm, `${hook} hook`) } } } if (vm._hasHookEvent) { vm.$emit('hook:' + hook) } }
  • 對外的生命週期函式需要主動捕獲其過程發生的錯誤,避免整個Vue例項生成過程終止
  • 生命週期函式存放位置 const handlers = vm.$options[hook]
  • 可以通過 $on 進行監聽事件 vm.$emit('hook:' + hook)

vm._hasHookEvent

  • 初始化事件相關initEvents函式中賦值為 false
  • 事件註冊例項方法 $on 中賦值為 true
  • callHoook函式中判斷_hasHookEvent是否為true

原始碼地址:https://github.com/vuejs/vue/blob/master/src/core/instance/events.js#L52

export function eventsMixin (Vue: Class<Component>) {
  const hookRE = /^hook:/
  Vue.prototype.$on = function (event: string |
Array<string>, fn: Function): Component { const vm: Component = this if (Array.isArray(event)) { for (let i = 0, l = event.length; i < l; i++) { this.$on(event[i], fn) } } else { (vm._events[event] || (vm._events[event] = [])).push(fn) // optimize hook:event cost by using a boolean flag marked at registration // instead of a hash lookup if (hookRE.test(event)) { vm._hasHookEvent = true } } return vm }

const hookRE = /^hook:/ 註冊事件以 hook: 開頭

實現方式

常規方式

子元件修改;

mounted() {
  this.$emit("mounted");
}

父元件中呼叫:

<Child @mounted="doSomething"></Child>

缺點: 需要修改子元件原始碼,增加相關 $emit 事件

$options方式

通過 refs 獲取相關元件例項,然後增加相應的 lifecycle hook

mounted () {
  const HelloWorldVmOption = this.$refs['HelloWorldRef'].$options
  if (!HelloWorldVmOption['updated']) HelloWorldVmOption['updated'] = []
  HelloWorldVmOption['updated'].push(() => {
    ...
  })
}

缺點: 由於 refs 只能在 mounted 及以後的生命週期中獲取,因此這種方式只能監聽子元件 mounted 以後的 lifecycle hook。

@hook:event

<Child @hook:mounted="doSomething"></Child>

在 vue2 中,完美解決!不需要修改原始碼~~