vue 生命周期

85 阅读3分钟

beforeCreate

实例初始化之后,this指向创建的实例,数据观测(data observer)和event/watcher配置尚未完成,不能访问到methodsdatacomputedwatch上的方法和数据。

created

完成以下配置:数据观测(data observer),属性和方法的运算,watch/event事件回调。尚未挂载到DOM,不能访问到$el属性,$ref内容为空数组。此时可以访问methods中定义的方法,修改data数据,并可触发响应式变化、computed值重新计算,watch到变更等。

此时若想进行DOM操作,可以使用$nextTicksetTimeout等异步函数。

beforeMount

beforeMount之前,会找到对应的template,并编译成render函数 (这个步骤如果使用.vue文件和运行时版本将会在构建时提前完成)

template查找的优先级顺序: template参数 > el 外部HTML 如果指定了render函数,则直接采用render函数,即忽略template参数和el外部HTML

mounted

el被新创建的$el替换,实例挂载到DOM上,此时可以通过DOM API获取到DOM节点,$ref属性可以访问。虽然经常观察到先进入子组件mounted,但根据Vue官方文档:

注意 mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染 完毕,可以用 [vm.$nextTick](https://cn.vuejs.org/v2/api/#vm-nextTick) 在这个阶段改变data上的值,相关的computed属性可以立刻更新;但需要进入到下一次DOM更新,才能看到DOM上数据更新(会触发updated,然后更新DOMmounted中拿到DOM时不会更新--还没有来得及更新)。

beforeUpdate

这里的更新对象是模板,即需要虚拟 DOM 重新渲染和打补丁,beforeUpdate发生在以上两个流程之前,此时新的虚拟DOM已经生成。

如果发生变更的数据在模板中并没有使用(包括直接和间接,间接:比如某个依赖该数据的计算属性在模板中使用了),则不会触发更新流程。若变更操作不是基础类型的简单赋值且数据在模板中使用,可能会引起死循环(不断重新进入beforeUpdate)。

new Vue({
  el: '#app',
  template: '<p id="testa">{{a}}</p>',
  router,
  data ()
  {
    return {
      a : 0,
      c:  0
    }
  },
  beforeUpdate() {
    console.log(document.getElementById('testa').innerHTML)
    // this.c = 1;   //  this.c没有在模板中使用,变更不会引起重渲染流程
    // this.a = 3;  //  会再次进入一次重渲染流程,第二次进入时发现a仍是3,值没有变更,不会再次重渲染
    // this.a ++;   //  会引起死循环,每次进入重渲染流程时,a的值都会变更
  },
  updated() {
    console.log(document.getElementById('testa').innerHTML)
  }
})

beforeUpdate中可以监听data的变化,但是View没有被重新渲染,View的数据没有变化,等到updated的时候,View重新渲染,数据更新。注:鉴于上述代码中提到的问题,应避免在这个钩子中操作数据。

updated

由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。 当这个钩子被调用时,组件DOM 已经更新,可以执行依赖于 DOM 的操作。

注意 updated 不会承诺所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以用 [vm.$nextTick](https://cn.vuejs.org/v2/api/#vm-nextTick)

同样,应该避免在这个钩子函数中操作数据。

beforeDestory

实例销毁之前调用。在这一步,实例仍然完全可用,this仍能获取到实例。一般在这一步中进行:销毁定时器、解绑全局事件、销毁插件对象等操作。

destroyed

Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

注意:vue2.0之后主动调用$destroy()不会移除dom节点,作者不推荐直接destroy这种做法,具体参考 github.com/vuejs/vue/i…

其他

<keep-alive>组件相关

在使用<keep-alive>组件时,生命周期钩子函数不会被重复调用(beforeUpdateupdated除外),如果我们的子组件需要在每次加载的时候进行某些操作,可以使用activated钩子。

vue中父子组件生命周期顺序

  • 加载渲染过程:父组件(beforeCreate->created->beforeMount)->子组件(beforeCreate->created->beforeMount->mounted)->父组件(mounted
  • 子组件更新过程:父beforeUpdate->子(beforeUpdate->updated)->父updated
  • 父组件更新过程:父beforeUpdate->父updated
  • 销毁过程:父beforeDestroy->子(beforeDestroy-> destroyed)->父destroyed

从上面的加载顺序可以看出,无论是加载渲染还是更新、销毁过程,都是先调用父组件钩子完成相应的父组件准备操作(只差一个DOM操作),然后完成子组件全部操作,最后再进行父组件的DOM操作。