每个 Vue 实例在被创建时都要经过一系列的初始化过程,例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

生命周期图示与生命周期钩子

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

生命周期 - 图2

生命周期钩子

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

生命周期 - 图3

beforeCreate

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

  1. <div id="app">
  2. <div @click="handleClick">点击事件</div>
  3. </div>
  1. const vm = new Vue({
  2. el: '#app',
  3. data: {
  4. msg: 'hellow world',
  5. },
  6. beforeCreate () {
  7. console.log(this.msg); // undefined
  8. console.log(this.handleClick); // undefined
  9. console.log('-----beforeCreate-----');
  10. },
  11. methods: {
  12. handleClick () {
  13. console.log(handleClick);
  14. }
  15. },
  16. watch: {
  17. msg: {
  18. handler () {
  19. console.log('侦听msg的值');
  20. },
  21. immediate: true,
  22. }
  23. }
  24. })

打印顺序:
image.png

created

在实例创建完成后被立即调用。
在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。
如果要在第一时间调用methods中的方法,或者操作data中的数据,可在此钩子中进行操作。
需要注意的是,执行此钩子时,挂载阶段还未开始,$el 属性目前不可见。
此时,可以进行数据请求,将请求回来的值赋值给data中的数据。

  1. <div id="app">
  2. <div @click="handleClick">点击事件</div>
  3. </div>
  1. const vm = new Vue({
  2. el: '#app',
  3. data: {
  4. msg: 'hellow world',
  5. },
  6. created () {
  7. console.log(this.msg); // hello world
  8. console.log(this.handleClick); // function () {...}
  9. console.log(this.$el); // undefined
  10. console.log('----------created-------');
  11. },
  12. methods: {
  13. handleClick () {
  14. console.log(handleClick);
  15. }
  16. },
  17. watch: {
  18. msg: {
  19. handler () {
  20. console.log('侦听msg的值');
  21. },
  22. immediate: true,
  23. }
  24. }
  25. })

打印顺序:

  1. 侦听msg的值
  2. hellow world
  3. ƒ handleClick () { console.log(handleClick); }
  4. undefined
  5. ----------created-------

beforeMount

在挂载开始之前被调用,此时模板已经编译完成,只是未将生成的模板替换el对应的元素。
在此钩子函数中,可以获取到模板最初始的状态。
此时,可以拿到vm.$el,只不过为旧模板

  1. const vm = new Vue({
  2. el: '#app',
  3. beforeMount () {
  4. console.log(this.$el);
  5. }
  6. })

上面的旧模板是指使用vue写的html代码,如下图
image.png

mounted

el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。
在该钩子函数中的vm.$el为新模板。
执行完该钩子函数后,代表实例已经被完全创建好。
如果要在第一时间,操作页面上的dom节点时,可以在此钩子函数中操作

  1. const vm = new Vue({
  2. el: '#app',
  3. mounted () {
  4. console.log(this.$el);
  5. }
  6. })

beforeUpdate

数据更新时调用,发生在虚拟 DOM 打补丁之前。此时数据已经更新,但是DOM还未更新

  1. <div id="app">
  2. {{ msg }}
  3. </div>
  1. const vm = new Vue({
  2. el: '#app',
  3. data: {
  4. msg: 'hellow world',
  5. },
  6. beforeUpdate () {
  7. console.log(this.msg);
  8. console.log(this.$el); // 此时直接输出的元素是DOM重新渲染后的,因为console.log里的值是引用值,当你输出时会输出已经修改的值
  9. console.log(this.$el.outerHTML);
  10. },
  11. methods: {
  12. handleClick () {
  13. console.log('handleClick');
  14. }
  15. }
  16. })
  17. this.msg = 'xxx';

image.png
由于console.log(this.$el) 中的 this.$el 是引用值可参考下面的案例,故使用 this.$el.outerHTML

  1. let a = {};
  2. console.log(a,'此时对象a还未添加任何属性'); // 第一次打印中虽然看起来是空值,当时展开看是有值得
  3. a.name = 'zzz';
  4. console.log(a,'此时对象a已将添加name属性');//不用展开就能看到值

控制台打印
image.png

updated

数据更改导致DOM重新渲染后,会执行该钩子函数。
此时数据和dom同步。

beforeDestroy

实例销毁之前调用。在这一步,实例仍然完全可用。
可以在该钩子函数中,清除定时器。

  1. <div id="app">
  2. {{ msg }}
  3. </div>
  1. const vm = new Vue({
  2. el: '#app',
  3. data: {
  4. msg: 'hellow world',
  5. timer: 0,
  6. },
  7. created () {
  8. this.timer = setInterval(() => {
  9. console.log('xxx');
  10. }, 500)
  11. },
  12. beforeDestroy () {
  13. clearInterval(this.timer);
  14. }
  15. })

destroyed

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