请详细说下你对Vue生命周期的理解(源码)

请详细说下你对Vue生命周期的理解

    • 什么是Vue生命周期
      • 生命周期钩子
        • beforeCreate
        • created
        • beforeMount
        • mounted
        • beforeUpdate
        • updated
        • activated
        • deactivated
        • beforeDestroy
        • destroyed
      • 钩子怎么触发
        • 把所有同类钩子先合并成数组,然后存放在 vm.$options
        • 初始化设置一些标志位,表明是否已经完成某种钩子
      • 钩子怎么执行
      • 钩子什么时候触发(源码)

什么是Vue生命周期

Vue 实例有一个完整的生命周期,也就是从开始创建初始化数据编译模版挂载Dom -> 渲染更新 -> 渲染卸载等一系列过程,我们称这是Vue的生命周期

总共分为8个阶段:

  • 创建前/后(beforeCreate/created)
  • 载入前/后(beforeMount/mounted)
  • 更新前/后(beforeUpdate/updated)
  • 销毁前/后(beforeDestory/destoryed)

生命周期钩子

Vue的生命周期过程也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

所有的生命周期钩子自动绑定 this 上下文到实例中,因此你可以访问数据,对 property 和方法进行运算。

这意味着你不能使用箭头函数来定义一个生命周期方法 (例如 created: () => this.fetchTodos())。
这是因为箭头函数绑定了父上下文,因此 this 与你期待的 Vue 实例不同。

请详细说下你对Vue生命周期的理解(源码)_第1张图片

beforeCreate

在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。

created

在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer)property 和方法的运算watch/event 事件回调。然而,挂载阶段还没开始,$el property目前尚不可用

beforeMount

在挂载开始之前被调用:相关的 render 函数首次被调用,
该钩子在服务器端渲染期间不被调用。

mounted

实例被挂载后调用,这时 el 被新创建的 vm.$el 替换了。如果根实例挂载到了一个文档内的元素上,当 mounted 被调用时 vm.$el 也在文档内。
注意
mounted 不会保证所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以在 mounted 内部使用 vm.$nextTick

该钩子在服务器端渲染期间不被调用。

mounted: function () {
     
  this.$nextTick(function () {
     
    // Code that will run only after the
    // entire view has been rendered
  })
}

beforeUpdate

数据更新时调用,发生在虚拟 DOM 打补丁之前(即视图未更新)。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。

该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行。

updated

由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。

当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。
然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。

注意 updated 不会保证所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以在 updated 里使用 vm.$nextTick

该钩子在服务器端渲染期间不被调用。

updated: function () {
     
  this.$nextTick(function () {
     
    // Code that will run only after the
    // entire view has been re-rendered
  })
}

activated

被 keep-alive 缓存的组件激活时调用。
该钩子在服务器端渲染期间不被调用。

deactivated

被 keep-alive 缓存的组件停用时调用。
该钩子在服务器端渲染期间不被调用。

beforeDestroy

实例销毁之前调用。在这一步,实例仍然完全可用。
该钩子在服务器端渲染期间不被调用。

destroyed

实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。

该钩子在服务器端渲染期间不被调用。

钩子怎么触发

首先,我设置了下面的例子

new Vue({
     
	el:document.getElementsByTagName('div')[0],
	created() {
     
		console.log('created被触发')
	}
)

el 和 created 就是传入 Vue 的自定义选项

把所有同类钩子先合并成数组,然后存放在 vm.$options

合并,主要是为了把全局设置的钩子组件自定义的钩子合并起来,就算你没有全局钩子,也要存在数组里面,比如 created 是下面

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

初始化设置一些标志位,表明是否已经完成某种钩子

function initLifecycle(vm) {
     
    vm._isMounted = false;
    vm._isDestroyed = false;
    vm._isBeingDestroyed = false;
}

这个函数会在 beforeCreated 钩子触发前调用,在 Vue.prototype._init 中,下个问题源码有显示。其中的标志位什么时候设置呢,是在相应的钩子触发之后,具体看下面源码

钩子怎么执行

通过下面 这个函数

function callHook(vm, hook) {
         
    // 是自己传入的 created 等回调
    var handlers = vm.$options[hook];    
    if (handlers) {
     
    // 执行多个同名钩子    
    for (var i = 0,j = handlers.length; i < j; i++) {
     
            handlers[i].call(vm);
        }
    }
}

比如触发 created 就会这么调用
callHook(vm,‘created’)
直接拿到钩子,然后遍历执行,绑定上下文对象。

为什么是数组?,一个实例通过mixins可能有很多个相同钩子,所以合并成的数组

钩子什么时候触发(源码)

源码如下,只列出常用的几个钩子

function Vue(opt){
         
    this._init(opt)
}


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');
}

谢谢你阅读到了最后
期待你 点赞、评论、收藏、关注

你可能感兴趣的:(Vue,vue,生命周期)