Vue之HookEvent

前言

什么是HookEvent?实际上是Vue中提供的一类与生命周期相关的事件,这些事件的触发与生命周期函数调用存在关联。我们知道Vue2.x提供了一些生命周期函数,用于提供开发者对于特殊逻辑点的逻辑处理。本文内容实际上分为2个部分:

  • 生命周期函数调用
  • HookEvent

生命周期函数调用

实际上Vue源码对于生命周期对应函数的调用都是通过callHook函数来处理的,该部分逻辑实际上关注点也就几个:

  function callHook (vm, hook) {
      // #7573 disable dep collection when invoking lifecycle hooks
      pushTarget();
      var handlers = vm.$options[hook];
      var info = hook + " hook";
      if (handlers) {
        for (var i = 0, j = handlers.length; i < j; i++) {
          invokeWithErrorHandling(handlers[i], vm, null, vm, info);
        }
      }
      if (vm._hasHookEvent) {
        vm.$emit('hook:' + hook);
      }
      popTarget();
    }

实际上通过上面源码有3点信息:

  • 生命周期函数都是存在vue实例的$options属性中的
  • 函数的处理调用invokeWithErrorHandling函数
  • 当_hasHookEvent存在时会触发hook:created类似的事件
invokeWithErrorHandling

实际上通过该函数名称可以大概知道该函数的功能:带有错误处理功能的调用。实际上该函数的功能就是如此,对外的生命周期函数需要主动捕获其过程发生的错误,不然回会导致整个Vue实例生成过程终止。具体源码逻辑如下:

    function invokeWithErrorHandling (
      handler,
      context,
      args,
      vm,
      info
    ) {
      var res;
      try {
      	// 执行生命周期函数
        res = args ? handler.apply(context, args) : handler.call(context);
        if (res && !res._isVue && isPromise(res) && !res._handled) {
          res.catch(function (e) { 
          	return handleError(e, vm, info + " (Promise/async)"); 
          });
          // issue #9511
          // avoid catch triggering multiple times when nested calls
          res._handled = true;
        }
      } catch (e) {
        handleError(e, vm, info);
      }
      return res
    }
HookEvent

HookEvent是Vue定义的与生命周期相关的事件类型,其具体形式是:

hook:生命周期名称

生命周期函数调用中(callHook函数中)有该类事件的触发入口,即:

if (vm._hasHookEvent) {
    vm.$emit('hook:' + hook);
}

从上面逻辑中可知_hasHookEvent是该类事件触发的前置条件,而该实例属性的应用在Vue源码中有3处地方:

  • initEvents函数中赋值操作
  • 事件注册实例方法$on中赋值操作
  • callHoook函数中判断_hasHookEvent是否为true

实际上initEvents是初始化事件相关的处理,这里_hasHookEvent并赋值为false,核心逻辑在事件注册实例方法$on中,具体逻辑如下:

   var hookRE = /^hook:/;
   Vue.prototype.$on = function (event, fn) {
        var vm = this;
        if (Array.isArray(event)) {
          for (var i = 0, l = event.length; i < l; i++) {
            vm.$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
 };

从上面可以知道_hasHookEvent开启的条件是:

$on注册事件是hook:开头的并且是单个事件处理程序

从上面的整体逻辑可知HookEvent相关信息:

当实例注册了hook:开头的事件后,会在生命周期钩子函数调用时触发对应的hook事件,例如hook:created、hook:mounted等

HookEvent应用场景

从上面可知道hook event开启的条件以及事件执行的事件点,那么为什么会存在HookEvent这样特殊的事件呢?
在日常开发过程中,经常是直接在vue组件中显式调用生命周期函数,例如:

mounted() {
	// 相关处理
}

HookEvent逻辑的存在就允许通过js来动态添加生命周期,例如:

created() {
	this.$on('hook:mounted', function() {});
}

但是这样的场景不常见而且也是比较怪异的。通过HookEvent的相关逻辑分析,更常见合理的场景应该是:

从外部注入生命周期事件

比如第三方的Vue组件el-select,我想从外部注入mounted生命周期函数。

<el-select ref="select" @hook:mounted="callback"></el-select>
// 获取select实例注册
this.$refs['select'].$on('hook:mounted', function() {})

通过外部注入HookEvent可以在组件对应的生命周期时间点触发外部相关逻辑。目前个人倒是没有遇到这样的实际场景,可见这种场景在日常业务开发中是并不多见的。

总结

HookEvent定义:

是指定义以生命周期命名的固定形式的特殊事件,形式如:hook:created、hook:mounted等。

该类事件触发时机:

组件对应的生命周期函数执行后

使用场景:

从外部注入对应子组件的HookEvent,在指定的生命周期执行时间点执行相关的外部逻辑

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值