• Vue源码学习(二)——生命周期


    官网对生命周期给出了一个比较完成的流程图,如下所示:

    从图中我们可以看到我们的Vue创建的过程要经过以下的钩子函数:

    
    beforeCreate => created => beforeMount => mounted
    => beforeUpdate => updated
    => beforeDestroy => destroyed
    

    那么我们就从源码的角度来看一看吧,当我们new Vue的时候,会执行_init函数

    
    function Vue (options) {
      if (process.env.NODE_ENV !== 'production' &&
        !(this instanceof Vue)
      ) {
        warn('Vue is a constructor and should be called with the `new` keyword')
      }
      this._init(options)
    }
    

    init函数如下

    
    export function initMixin (Vue: Class<Component>) {
      Vue.prototype._init = function (options?: Object) {
        ....
        以下就是进行了生命周期
        vm._self = vm
        // 首先进行初始化生命周期的参数
        initLifecycle(vm)
        // 在初始化事件
        initEvents(vm)
        // 初始化render
        initRender(vm)
        // 开始调用beforeCreate钩子函数,和图中的流程图一样
        callHook(vm, 'beforeCreate')
        // 之后开始初始化变量等一些数据
        initInjections(vm) // resolve injections before data/props
        initState(vm)
        initProvide(vm) // resolve provide after data/props
        // 开始调用created钩子函数
        callHook(vm, 'created')
    
        /* istanbul ignore if */
        if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
          vm._name = formatComponentName(vm, false)
          mark(endTag)
          measure(`vue ${vm._name} init`, startTag, endTag)
        }
    
        if (vm.$options.el) {
          vm.$mount(vm.$options.el)
        }
      }
    }
    

    以上init函数我们已经看到了beforeCreate和created,那么callHook是怎么调用的钩子函数呢?

    
    export function callHook (vm: Component, hook: string) {
      // #7573 disable dep collection when invoking lifecycle hooks
      pushTarget()
      // 从$options里拿到钩子函数
      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)
      }
      popTarget()
    }
    

    这边就会有几个问题:
    从vm.$options[hook]中取钩子函数,那个这个钩子函数是哪来来的? 为了拿到的钩子函数是个数组?我们平时使用不都是只是写个函数吗?

    我们可以看到在$options是在下面_init中进行合并的

    
    Vue.prototype._init = function(){
        ...
        vm.$options = mergeOptions(
            resolveConstructorOptions(vm.constructor),
            options || {},
            vm
          )
          ...
    }
    
    export const LIFECYCLE_HOOKS = [
      'beforeCreate',
      'created',
      'beforeMount',
      'mounted',
      'beforeUpdate',
      'updated',
      'beforeDestroy',
      'destroyed',
      'activated',
      'deactivated',
      'errorCaptured'
    ]
    
    

    我们可以看到钩子函数一开始就已经在vue内部已经定义好了,并且还有几个钩子函数不是实话化实例的使用执行的。而是对keep-alive组件配合使用的activated,deactivated。以及错误抛出钩子函数errorCaptured
    然后再根据这些内部定义的钩子函数和传入的参数进行合并

    那么为什么钩子函数是数组呢?这个其实很简单是因为vue内部也需要执行一些函数,顾把函数也放到钩子函数里。所以需要数组遍历。

    所以这些所谓的钩子函数就是一个回调函数。

    其余几个钩子函数也是在需要调用的时候使用callHook(vm, 'xxx')来执行

    如果对您有帮助请点个赞,谢谢!

    原文地址:https://segmentfault.com/a/1190000016906255

  • 相关阅读:
    ruoyi管理系统建立子项目,卡住
    JSON
    各类求自然数幂和方法
    一个关于序列区间gcd的小trick
    【JZOJ6654】【2020.05.27省选模拟】数据结构
    【JZOJ6569】【GDOI2020模拟】夕张的改造 (kaisou)
    拉格朗日插值法
    【JZOJ1914】【2011集训队出题】最短路
    【JZOJ4817】【NOIP2016提高A组五校联考4】square
    【JZOJ4816】【NOIP2016提高A组五校联考4】label
  • 原文地址:https://www.cnblogs.com/lalalagq/p/9916317.html
Copyright © 2020-2023  润新知