在以前的 Vue 学习中,咱们在使用 Vue 时,都会建立一个 Vue 的实例,而每一个 Vue 实例在被建立时都要通过一系列的初始化过程。例如,须要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。在这个过程当中,Vue 会运行一些生命周期钩子函数,而咱们则能够在钩子函数中编写一些自定义方法,用以在 Vue 的整个生命周期中某些阶段实现咱们特殊需求。那么,本章,咱们就来了解 Vue 实例的生命周期钩子函数。html
学习系列目录地址:http://www.javashuo.com/article/p-bzzucmub-ba.htmlvue
仓储地址:https://github.com/Lanesra712/VueTrial/blob/master/Chapter01-Rookie/hocks.htmlgit
在咱们使用 Vue 的时候,都会先建立一个 Vue 实例,这个实例不只是咱们挂载 Vue 框架的入口,也是 MVVM 思想中的 VM(ViewModel)。在咱们使用 Vue 的整个过程当中,归根结底都是在对这个 Vue 实例进行操做。所以,只有当咱们了解 Vue 实例的生命周期以后,才能够更好的实现咱们的业务逻辑。github
在 Vue 官网的这张生命周期图示中,咱们能够看到整个生命周期中包含了8个钩子函数:beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed。从字面意思咱们就能够清楚的看出来,这8个钩子函数两个一组,分别对应于 Vue 实例的建立、挂载、更新、销毁,接下来,咱们就根据这四个阶段,解释 Vue 实例各个阶段中的钩子函数的做用。segmentfault
在咱们经过 new Vue() 建立了一个 Vue 实例以后,会执行 init 方法,此时只会初始化 Vue 实例所包含的一些默认的事件与生命周期函数,在这个实例还未被彻底建立以前,则会执行咱们的 beforeCreate 钩子函数。浏览器
在下面的例子中,咱们在实例化 Vue 对象时,自定义了一个 message 属性,同时设定了一个 show 方法,如今咱们来看看当实例并无彻底被建立以前,是否可以获取到咱们自定义的属性与方法。app
<div id="app"> {{message}} </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('执行了 show 方法'); } }, beforeCreate() { console.log(`Vue 实例挂载对象 el:${this.$el}`) console.log(`Vue 实例的 data 对象:${this.$data}`) console.log(`Vue 实例的 message 属性值:${this.message}`) console.log(`Vue 实例的 methods 对象:${this.$options.methods}`) this.show(); } }) </script>
从浏览器的控制台中咱们能够看到,此时,Vue 实例中的 data、methods 对象,或是咱们定义的 Vue 实例的挂载点元素,在 beforeCreated 生命周期钩子函数执行时,都没有进行了初始化。框架
当 beforeCreated 钩子函数执行完成后,Vue 实例已经初始化完成,此时将要执行生命周期中的 created 钩子函数来监听咱们对于数据的更改或是监听事件。函数
<div id="app"> {{message}} </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('执行了 show 方法'); } }, created() { console.log(`Vue 实例挂载对象 el:${this.$el}`) console.log(`Vue 实例的 data 对象:${this.$data}`) console.log(`Vue 实例的 message 属性值:${this.message}`) console.log(`Vue 实例的 methods 对象:${this.$options.methods}`) this.show(); } }) </script>
从浏览器控制台打印出的信息能够看出,在执行 created 钩子函数的过程当中,对于自定义的属性 message、自定义的方法 show 已经初始化完成,此时,整个 Vue 实例已经初始化完成。可是,对于咱们的 Vue 实例的挂载点元素尚未进行初始化。也就是说,当执行完 created 以后,Vue 实例与 View(视图层)之间依旧是处于隔离的状态,初始化完成的 Vue 实例也依旧没有与 DOM 进行绑定。post
当 Vue 实例执行完 beforeCreated、created 钩子函数以后,Vue 实例已经初始化完成,而 Vue 实例并无挂载到页面的 DOM 上。在挂载到页面 DOM 元素以前,则须要执行 beforeMount 钩子函数将咱们的实例绑定到模板上进行编译渲染。
<div id="app"> <h3 id="h3">{{message}}</h3> </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('执行了 show 方法'); } }, beforeMount() { console.log(document.getElementById('h3').innerText) } }) </script>
从控制台输出的信息能够看到,当执行到 beforeMount 钩子函数时,已经将模板编译完成,可是还没有挂载到页面上去。
当把编译完成的模板挂载到页面上时,则须要执行 mounted 钩子函数,在这个阶段,用户就能够看到已经渲染好的页面。
<div id="app"> <h3 id="h3">{{message}}</h3> </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('执行了 show 方法'); } }, mounted() { console.log(document.getElementById('h3').innerText) } }) </script>
这里咱们能够看到,已经能够获取到差值表达式的值,即当执行到 mounted 钩子函数时,页面已经渲染完成了。
从上面的例子中能够看出,mounted 是建立 Vue 实例过程当中的最后一个生命周期钩子函数,当执行完 mounted 钩子函数以后,实例已经被完成建立好,并已经渲染到页面中,此时,若是咱们不对实例进行任何的操做的话,Vue 实例则不会执行 新的生命周期钩子函数。
在执行完了 mounted 钩子函数以后,Vue 实例实际已经脱离了实例的建立阶段,进入实例的运行阶段。此时,当咱们对实例的 data 进行修改时,则会触发 beforeUpdate、updated 这两个钩子函数。
<div id="app"> <h3 id="h3">{{message}}</h3> </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('执行了 show 方法'); } }, beforeUpdate() { console.log(`页面上的数据:${document.getElementById('h3').innerText}`) console.log(`data 中的 message 数据:${this.message}`) } }) </script>
咱们能够看到,当咱们对 data 中的 message 属性进行修改时,在执行 beforeUpdate 钩子函数时,页面上的数据仍是旧的数据,而 data 中 message 属性已经将值修改为了最新的值(这里页面上显示的为修改后的数据则是由于执行了后面的钩子函数,将修改后的数据同步渲染到了页面上)。
Vue 做为一个具备数据双向绑定特性的框架,当咱们实时修改了页面元素的值以后,确定但愿页面能够同步变动数据。而在执行 beforeUpdate 钩子函数以后,咱们已经在实例中修改了数据,如今只须要从新渲染到页面就能够了,这时候,则会执行 updated 钩子函数。
<div id="app"> <h3 id="h3">{{message}}</h3> </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('执行了 show 方法'); } }, updated() { console.log(`页面上的数据:${document.getElementById('h3').innerText}`) console.log(`data 中的 message 数据:${this.message}`) } }) </script>
从控制台能够看到,当 updated 钩子函数执行的时候,页面和 data 中的数据已经完成了同步,都显示的是最新的数据。此时,整个页面数据实时变动的操做也已经完成了。
既然有 Vue 实例的建立,那么在咱们不须要 Vue 实例的时候就须要将这个实例进行销毁。而 beforeDestroy 以及 destroyed 钩子函数则会帮咱们实现这一目的。
<div id="app"> {{message}} </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('执行了 show 方法'); } }, beforeDestroy() { console.log(`Vue 实例挂载对象 el:${this.$el}`) console.log(`Vue 实例的 data 对象:${this.$data}`) console.log(`Vue 实例的 message 属性值:${this.message}`) console.log(`Vue 实例的 methods 对象:${this.$options.methods}`) this.show(); }, destroyed() { console.log(`Vue 实例挂载对象 el:${this.$el}`) console.log(`Vue 实例的 data 对象:${this.$data}`) console.log(`Vue 实例的 message 属性值:${this.message}`) console.log(`Vue 实例的 methods 对象:${this.$options.methods}`) this.show(); } }) </script>
这里,咱们手动销毁 Vue 实例,从控制台的输出内容能够看到,在 beforeDestroy 和 destroyed 钩子函数执行中,咱们依旧能够获取到 Vue 实例的相关内容,但是,当咱们选择更新 message 属性的值时会发现,此时,页面上显示的值并无发生改变。原来,这里的销毁并不指代'抹去'这个 Vue 实例,而是表示将 Vue 实例与页面的 DOM 元素进行'解绑'。
钩子函数 | 描述 |
---|---|
beforeCreate | Vue 实例进行初始化,此时实例的各个组件尚未进行初始化完成,所以不能访问到 data、computed、watch、methods 上的方法和数据,同时,Vue 实例的挂载点也没有进行初始化 |
created | Vue 实例初始化完成,此时能够访问 data、computed、watch、methods 上的方法和数据,可是依旧没有进行 Vue 实例的挂载点初始化 |
beforeMount | 将实例绑定到模板并进行渲染,但并不会将实例挂载到页面上 |
mounted | 将渲染好的模板绑定到页面上,此时,Vue 实例已彻底建立好 |
beforeUpdate | 数据变动时调用,在实例数据更改以前执行任何应该发生的自定义逻辑或操做 |
updated | 将 Vue 实例更新完成的数据从新渲染到内存中的虚拟 DOM 上,再将虚拟 DOM 应用到页面上 |
beforeDestroy | Vue 实例进入销毁阶段,此时实例上的 data、methods、过滤器、指令等等仍是处于可用的状态,尚未真正执行销毁的过程(解除与页面 DOM 元素的绑定) |
destroyed | 实例被销毁(解除与页面 DOM 元素的绑定) |