Vue生命周期

Posted fiona-zhong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue生命周期相关的知识,希望对你有一定的参考价值。

Vue实例有一个完整的生命周期,即开始创建---》初始化数据---》编译模板---》挂载DOM---》渲染---》更新---》渲染---》销毁等一系列过程,这一系列过程我们称之为Vue实例的生命周期,钩子就是在某个阶段给你一个做某些处理的机会。

先上一张图来只管的感受一下Vue的生命周期:

技术图片

Vue生命周期主要以下几个钩子函数:

1、beforeCreate():

   我们在实例化Vue的时候(new Vue),会首先初始化事件和生命周期,然后会调用这个钩子函数,这个钩子函数我们一般不会使用它去做太多功能。

   这个时候,数据data和el还没有挂载到Vue实例上,只是一个空壳,是无法访问到数据data和真实的dom挂载元素el的。

2、created():

   在实例创建后,会挂载数据data和绑定事件。然后会调用created钩子函数,所以此时,实例已经完成了基本配置。

   这里可以使用数据data,也可以修改数据data,且这里的修改数据是不会触发updated钩子函数的。

      一般可以在这里做数据初始化的操作,不过如果请求过多且全部都是同步请求的话,可能会导致界面出现短暂的空白阻塞,所以是否在这里初始化请求数据,看个人需求。

   但是dom还是没有挂载到界面,所以$el依旧是不可见的。

  技术图片

3、beforeMount():

  实例基本配置完成后,会去判断实例是否有挂载el对象,如果有的话,就继续向下编译,如果没有的话,就停止编译,即意味着停止了生命周期,直到我们在该实例上手动挂载el,即调用vm.$mount("#app")

   这个钩子函数,我们基本上也是不会去使用它的。

   它的作用主要是用来检查,Vue实例中有没有自定义template参数选项,如果有的话,会将其作为模板template编译成虚拟dom放到render函数中准备渲染;但是如果我们已经自定义了render函数,会使用我们定义的render函数的返回值渲染到界面;如果都没有,就将挂载元素el的html作为模板template编译。

  可以看到自定义render函数优先级 > 自定义template参数选项 >  挂载元素el的outer HTML

  此時,我們就可以理解,为啥要先去判断是否有挂载el对象了,因为我们需要通过el找到对应的out template

  找到实例或组件对应的模板,编译成虚拟dom放入到render函数中,准备渲染,然后会执行beforeMount钩子函数,这个函数中,虚拟dom已经创建完成,即将渲染。这里我们还可以修改data且不触发updated钩子函数,这将是我们不触发updated钩子函数去修改data的最后一次机会了,后面所有的修改都将触发updated钩子函数。

<div id=‘app‘>{{a}}</div>

new Vue({
    data(){
        return {
            a:100,
        }
    },
    template:"<h1>{{a}}</h1>",
    render(createElement){
        return createElement("h2",{
            attrs:{
                id:"aaa"
            },
            style:{
                border:"1px solid red"
            },
            on:{
                click(){
                    alert(1)
                }
            }
        },‘this is a render fn‘)
    },
    beforeMount(){
        // 这里会去检查我们是否有自定义render(),有的话,会将render函数的返回值渲染到app中,如果没有render函数,会去查找是否有自定义template,有的话将template值渲染到app中
    }
})

4、mounted():

  接下来render后,渲染出真实dom,然后执行mounted()钩子函数。

  此时,组件已经出现在页面中,数据,真实dom都已经处理好了,事件也已经挂载好了,可以操作真实dom对象了。

  这里修改数据data,会触发updated钩子,需要注意的是,vue中所有的数据渲染都是异步的,这里我们通过 this.$el.innerHTML 是拿不到更新后的内容的,需要通过vue.$nextTick 去获取

<div id=‘app‘>{{a}}</div>

new Vue({
    el:"#app",
    data(){
        return {
            a:"hello"
        }
    },
    mounted(){
        this.a = 100;
        console.log(this.$el.innerHTML);
        this.$nextTick(()=>{
       // 会在updated钩子函数之后执行 console.log(
"nextTick->",this.$el.innerHTML) }) } });

技术图片

5、beforeUpdate() 和 updated():

  当组件和实例中的数据发生变化后,会立即执行beforeUpdate钩子,然后vue的虚拟dom机制会重新创建新的虚拟dom,与上一次的虚拟dom树利用diff算法进行对比后,重新渲染组件。

  更新完成后,会执行updated钩子,数据和组件都已经更新完成,这是可以操作更新后的dom

  注意:updated()钩子函数中不能再修改数据,否则会造成死循环

7、beforeDestroy():

  当经过某种途径调用$destroy()后(如组件销毁,路由切换或者手动调用vm.$destroy()),在实例销毁之前,会立即触发beforeDestroy钩子。

  此时实例还是完全可用的。

  一般在这里做一些清扫工作,如清除定时器,清除非指令绑定事件等等。

<div id="app">
    <self-comp></self-comp>
<div>

<template>
    <div id="selfComp">
        <button @click="destroy">销毁</button>
        <h1>{{count}}</h1>
    </div>
</template>

Vue.component("selfComp",{
    template:"#selfComp",
    data(){
        return {
            count:1,
        }
    },
    timer:null,
    methods:{
        destroy(){
            this.$destroy();
        }
    },
    mounted(){
        this.$options.timer = setInterval(function(){
            this.count+=1;
        }.bind(this),1000);
    },
    beforeDestroy(){
        clearInterval(this.$options.timer);
    }
})

new Vue({}).$mount("#app")

 

以上是关于Vue生命周期的主要内容,如果未能解决你的问题,请参考以下文章

Android片段生命周期:onResume调用了两次

在不存在的片段上调用片段生命周期和 onCreate 的问题

导航上的片段生命周期重叠

Android 片段生命周期

关于片段生命周期,何时调用片段的 onActivityResult?

理解片段事务期间片段的生命周期方法调用