Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【源码】生命周期 源码解析 #43

Open
YIngChenIt opened this issue Jul 3, 2020 · 0 comments
Open

【源码】生命周期 源码解析 #43

YIngChenIt opened this issue Jul 3, 2020 · 0 comments

Comments

@YIngChenIt
Copy link
Owner

【源码】生命周期 源码解析

前言

生命周期的源码比较简单,这里就不从入口开始一步一步讲了

源码解析

我们知道Vue的mixin机制会把生命周期的回调函数存在一个数组中

vm.$options={
    mounted:[fn,fn,fn...]
}

然后Vue源码是通过callHook函数来调用这些回调,达到生命周期执行的效果, 如

 Vue.prototype._init = function (options) {
      vm._self = vm;
      initLifecycle(vm);
      initEvents(vm);
      initRender(vm);
      callHook(vm, 'beforeCreate');
      initInjections(vm); // resolve injections before data/props
      initState(vm);
      initProvide(vm); // resolve provide after data/props
      callHook(vm, 'created');
 }

因为initState的执行在beforeCreatecreated 之间,所以在beforeCreate生命周期里面是拿不到data数据的

我们来看一下callHook函数

export function callHook (vm: Component, hook: string) {
  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()
}

从代码上我们可以发现两个点

  • 内部很简单,是通过遍历数组的形式让生命周期的回调函数执行

  • 向外暴露事件hook, 这也是为什么我们可以通过@hook来获取到某个组件的生命周期的原因

我们对生命周期的原理有了大致了解之后,我们再来看下各个生命周期都在什么时候执行

// Vue初始化的时候
Vue.prototype._init(opt){
    ... 合并选项
    ... 设置初始值 ,事件 等数据
    initLifecycle(vm)
    callHook(vm, 'beforeCreate');
    ... 初始化选项等数据
    callHook(vm, 'created');
    ...获取挂载的DOM 父节点
    callHook(vm, 'beforeMount');
    ...解析模板成渲染函数,并执行渲染函数,生成DOM插入页面
    vm._isMounted = true;
    callHook(vm, 'mounted');
}

// 组件更新的时候
Vue.prototype._update = function(
    vnode, hydrating
) {    
    if (vm._isMounted) {
        callHook(vm, 'beforeUpdate');
    }
    ...重新调用渲染函数,对比旧节点和新节点,得到最小差异,然后只更新这部分页面
    callHook(vm, 'updated');
}

// 节点被移除时会调用这个函数
Vue.prototype.$destroy = function() {
    callHook(vm, 'beforeDestroy');
    vm._isBeingDestroyed = true;
    ...实例被消除,移除所有 watcher
    vm._isDestroyed = true;
    ...DOM被移除
    callHook(vm, 'destroyed');
}

总结

生命周期的源码超级简单,就是遍历mixin机制合并之后的生命周期回调函数数组,然后依次执行,但是我们也发现了另外一点就是我们可以通过@hook获取到组件的生命周期

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant