[Vue 牛刀小试]:第七章 - Vue 实例的生命周期

 一、前言

   在之前的 Vue 学习中,我们在使用 Vue 时,都会创建一个 Vue 的实例,而每个 Vue 实例在被创建时都要经过一系列的初始化过程。例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。在这个过程中,Vue 会运行一些生命周期钩子函数,而我们则可以在钩子函数中编写一些自定义方法,用以在 Vue 的整个生命周期中某些阶段实现我们特殊需求。那么,本章,我们就来了解 Vue 实例的生命周期钩子函数。

  学习系列目录地址:https://www.cnblogs.com/danvic712/p/9549100.html

  仓储地址:https://github.com/Lanesra712/VueTrial/blob/master/Chapter01-Rookie/hocks.html

 二、干货合集

  在我们使用 Vue 的时候,都会先创建一个 Vue 实例,这个实例不仅是我们挂载 Vue 框架的入口,也是 MVVM 思想中的 VM(ViewModel)。在我们使用 Vue 的整个过程中,归根结底都是在对这个 Vue 实例进行操作。因此,只有当我们了解 Vue 实例的生命周期之后,才可以更好的实现我们的业务逻辑。

  在 Vue 官网的这张生命周期图示中,我们可以看到整个生命周期中包含了8个钩子函数:beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed。从字面意思我们就可以清楚的看出来,这8个钩子函数两个一组,分别对应于 Vue 实例的创建、挂载、更新、销毁,接下来,我们就根据这四个阶段,解释 Vue 实例各个阶段中的钩子函数的作用。

  1、beforeCreate & created

  在我们通过 new Vue() 创建了一个 Vue 实例之后,会执行 init 方法,此时只会初始化 Vue 实例所包含的一些默认的事件与生命周期函数,在这个实例还未被完全创建之前,则会执行我们的 beforeCreate 钩子函数。

  在下面的例子中,我们在实例化 Vue 对象时,自定义了一个 message 属性,同时设定了一个 show 方法,现在我们来看看当实例并没有完全被创建之前,是否能够获取到我们自定义的属性与方法。

<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 进行绑定。

  2、beforeMount & mounted

  当 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 实例则不会执行 新的生命周期钩子函数。

  3、beforeUpdate & updated

  在执行完了 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 中的数据已经完成了同步,都显示的是最新的数据。此时,整个页面数据实时变更的操作也已经完成了。

  4、beforeDestroy & destroyed

  既然有 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 元素的绑定)

 四、参考

  1、详解vue生命周期

  2、Vue2.0 探索之路——生命周期和钩子函数的一些理解

  3、vue生命周期详解

  4、vue生命周期探究(一)

  5、Vue生命周期深入

  6、Vue 数据绑定和响应式原理

  7、Vue.js – lifecycle hooks, the layman’s overview

posted @ 2018-12-13 09:56  墨墨墨墨小宇  阅读(1445)  评论(0编辑  收藏  举报