Vue的生命周期钩子

128 阅读3分钟

概念

每个Vue实例在被创建时都要经过一系列的初始化过程
例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等
同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会
所有的生命周期钩子自动绑定 this 上下文到实例中,因此你可以访问数据,对 property 和方法进行运算
这意味着你不能使用箭头函数来定义一个生命周期方法 (例如 created: () => this.fetchTodos())
这是因为箭头函数绑定了父上下文,因此 this 与你期待的 Vue 实例不同,this.fetchTodos 的行为未定义

所有生命周期钩子

beforeCreate     在实例初始化之后,数据观测data observer和event/watcher事件配置之前被调用
created          在实例创建完成后被立即调用
beforeMount      在挂载开始之前被调用
mounted          实例被挂载后调用
beforeUpdate     数据更新时调用,发生在虚拟DOM打补丁之前
updated          由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后调用
activated        被keep-alive缓存的组件激活时调用
deactivated      被keep-alive缓存的组件停用时调用
beforeDestroy    实例销毁之前调用,在这一步实例仍然完全可用
destroyed        实例销毁后调用
errorCaptured    当捕获一个来自子孙组件的错误时被调用

创建期的生命周期钩子

<div id="app">
    <h3 id="h3">{{ msg }}</h3>
</div>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        msg: 'ok'
      },
      methods: {
        show() {
          console.log('执行了show方法')
        }
      },
      beforeCreate() {
        console.log(this.msg)
        this.show()
      },
      created() {
        console.log(this.msg)
        this.show()
      },
      beforeMount() {
        console.log(document.getElementById('h3').innerText)
      },
      mounted() { 
        console.log(document.getElementById('h3').innerText)
      },
    });
  </script>

beforeCreate:实例刚在内存中被创建出来,还没有初始化好data和methods属性

beforeCreate() {
  console.log(this.msg)  //控制台没有打印任何内容
  this.show()            //函数方法未被执行
  }
在beforeCreate生命周期函数执行的时候,data和methods中的数据都还没有初始化

created:实例已经在内存中创建OK,此时data和methods已经创建OK,此时还没有开始编译模板

created() {
  console.log(this.msg)  //打印出ok
  this.show()            //打印出'执行了show方法'
}
如果要调用methods中的方法,或者操作data中的数据,最早只能在created中操作

beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中

beforeMount() {
  console.log(document.getElementById('h3').innerText)  //打印出{{ msg }}
}
在beforeMount执行的时候,页面中的元素,还没有被真正替换过来,只是之前写的一些模板字符串

mounted:此时已经将编译好的模板,挂载到了页面指定的容器中显示

mounted() { 
  console.log(document.getElementById('h3').innerText)  //打印出ok
}
mounted表示内存中的模板已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了

运行期间的生命周期函数

<div id="app">
    <input type="button" value="修改msg" @click="msg='No'">
    <h3 id="h3">{{ msg }}</h3>
 </div>
 <script>
    var vm = new Vue({
      el: '#app',
      data: {
        msg: 'ok'
      },
      methods: {
        show() {
          console.log('执行了show方法')
        }
      },
      beforeUpdate() {
        console.log('界面上元素的内容:' + document.getElementById('h3').innerText)
        console.log('data 中的 msg 数据是:' + this.msg)
      },
      updated() {
        console.log('界面上元素的内容:' + document.getElementById('h3').innerText)
        console.log('data 中的 msg 数据是:' + this.msg)
      }
   });
 </script>

beforeUpdate:状态更新之前执行此函数,此时data中的状态值是最新的 但是界面上显示的数据还是旧的,因为此时还没有开始重新渲染DOM节点

beforeUpdate() {
 console.log('界面上元素的内容:' + document.getElementById('h3').innerText)
 console.log('data 中的 msg 数据是:' + this.msg)
}
当执行beforeUpdate时,页面中的显示的数据还是旧的,此时data数据是最新的,页面尚未和最新的数据保持同步

updated:实例更新完毕之后调用此函数,此时data中的状态值和界面上显示的数据,都已经完成了更新,界面已经被重新渲染

updated() {
  console.log('界面上元素的内容:' + document.getElementById('h3').innerText)
  console.log('data 中的 msg 数据是:' + this.msg)
}
pdated 事件执行的时候,页面和 data 数据已经保持同步了,都是最新的

销毁期间的生命周期函数(使用次数较少)

beforeDestroy:实例销毁之前调用,在这一步实例仍然完全可用

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

详细资料点击:Vue 生命周期钩子