Vue生命周期详解

生命周期简介

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

其实Vue实例的生命周期,主要分为三个阶段,每个阶段都会执行不同的钩子函数,分别为

  • 挂载(初始化相关属性,例如watch属性,method属性)

    1. beforeCreate

    2. created

    3. beforeMount

    4. mounted

  • 更新(元素或组件的变更操作)

    1. beforeUpdate

    2. updated

  • 销毁(销毁相关属性)

    1. beforeDestroy

    2. destroyed

 

下面请看一张Vue生命进程图(图片可能有点大)

钩子函数:

第一步:

beforeCreate: Vue实例初始化之后,以及事件初始化,以及组件的父子关系确定后执行该钩子函数,一般在开发中很少使用

created: 在调用该方法之前,初始化会被使用到的状态,状态包括props,methods,data,computed,watch.

而且会实现对data中属性的监听,也就是在created的时候数据已经和data属性进行了绑定。(放在data中的属性当值发生改变的时候,视图也会改变)。同时也会对传递到组件中的数据进行校验。

所以在执行created的时候,所有的状态都初始化完成,我们也完全可以在该阶段发送异步的ajax请求,获取数据。

但是,在created方法中,是无法获取到对应的的$el选项,也就是无法获取Dom

请看如下代码:

 created() {
          console.log("created");
          console.log("el===", this.$el);// undefined
          console.log("data==", this.$data);// 可以获取数据
          console.log("foo==", this.foo);//可以获取数据
        },

第二步:

 

 

created方法执行完毕后,下面会判断对象中有没有el选项。如果有,继续执行下面的流程,也就是判断是否有template选项,

如果没有el选项,则停止整个生命周期的流程,直到执行了vm.$mount(el)

下面请看代码:

<script>
      const vm = new Vue({
        // el: "#app",  //去掉了el选项
        data: {
          foo: "fooData",
        },
        methods: {
        beforeCreate() {
          console.log("beforCreate");
        },
        created() {
          console.log("created");
          console.log("el===", this.$el);
          console.log("data==", this.$data);
          console.log("foo==", this.foo);
        },      
      });
    </script>

在上面的代码中,我们将el选项去掉了,运行上面的代码后,我们发现执行完created方法后,整个流程就停止了。

现在,我们不添加el选项,但是手动执行vm.$mount(el),也能够使暂停的生命周期进行下去。如下面代码

<script>
      const vm = new Vue({
        // el: "#app",//去掉了el选项
        data: {
          foo: "fooData",
        },
        methods: {      
        beforeCreate() {
          console.log("beforCreate");
        },
        created() {
          console.log("created");
          console.log("el===", this.$el);
          console.log("data==", this.$data);
          console.log("foo==", this.foo);
        },     
      });
      vm.$mount("#app");//添加了$mount方法
    </script>

下面请看图

我们继续向下看,就是判断在对象中是否有template选项。

第一:如果Vue实例对象中有template参数选项,则将其作为模板编译成render函数,来完成渲染。

第二:如果没有template参数选项,则将外部的HTML作为模板编译(template),也就是说,template参数选项的优先级要比外部的HTML

第三:如果第一条,第二条件都不具备,则报错

 

Vue需要通过el的“选择器”找到对应的template.也就是说,Vue首先通过el参数去查找对应的template.如果没有找到template参数,则到外部HTML中查找,找到后将模板编译成render

函数(Vue的编译实际上就是指Vue把模板编译成render函数的过程)。还有一点需要注意template参数的优先级比外部HTML的优先级要高。)如果同时有template模板与外部的html,

则会优先渲染template里面的数据

第三步:

接下来会触发`beforeMount`这个钩子函数:如下图

在执行该钩子函数的时候,虚拟`DOM`已经创建完成,马上就要渲染了,在这里可以更改`data`中的数据,不会触发`updated`, 其实在`created`中也是可以更改数据,也不会触发`updated`函数

测试代码如下:

beforeMount() {
          console.log("beforeMount");
          console.log("beforeMount el===", this.$el);
          console.log("data==", this.$data);
          //this.foo = "abc"; //修改数据
          console.log("foo==", this.foo);
        },

通过上面的代码,我们可以获取`el`中的内容,同时也可以修改数据。

但是,这里需要注意的输入的`el`中的内容,`{{foo}}`还没有被真正的数据替换掉。而且对应的内容还没有挂载到页面上。

下面执行了`Create VM.$el and replace "el" with it`

经过这一步后,在模板中所写的`{{foo}}`会被具体的数据所替换掉。

所以下面执行`mounted`的时候,可以看到真实的数据。同时整个组件内容已经挂载到页面中了,数据以及真实`DOM`都已经处理好了,可以在这里操作真实`DOM`了,也就是在`mounted`的时候,页面已经被渲染完毕了,在这个钩子函数中,我们可以去发送`ajax`请求。

第四步:如下图

当整个组件挂在完成后,有可能会进行数据的修改,当Vue发现data中的数据发生了变化,会触发对应组件的重新渲染,先后调用了beforeUpdate 和updated钩子函数。

 

updated之前beoreUpdate之后有一个非常重要的操作就是虚拟DOM会重新构建,也就是新构建的虚拟DOM与上一次的虚拟DOM树利用diff算法进行对比之后重新渲染。

而到了updated这个方法,就表示数据已经更新完成,dom也重新render完成。

第五步:

下面如果我们调用了vm.$destroy方法后,就会销毁所有的资源。

 

首先会执行beforeDestroy 这个钩子函数,这个钩子函数在实例销毁前调用,在这一步,实例仍然可用。

在该方法中,可以做一些清理的工作,例如:清除定时器等。

但是执行到destroyed钩子函数的时候,Vue实例已经被销毁,所有的事件监听器会被移除,所有的子实例也会被销毁

最后来个总结:

beforeCreate( )// 该钩子函数执行时,组件实例还未创建.
created()//组件初始化完毕,各种数据可以使用,可以使用ajax发送异步请求获取数据
beforeMounted()// 未执行渲染,更新,虚拟DOM完成,真实DOM未创建
mounted()// 初始化阶段结束,真实DOM已经创建,可以发送异步请求获取数据,也可以访问dom元素
beforeUpdate()//更新前,可用于获取更新前各种状态数据
updated()//更新后执行该钩子函数,所有的状态数据是最新的。
beforeDestroy() // 销毁前执行,可以用于一些定时器的清除。
destroyed()//组件已经销毁,事件监听器被移除,所有的子实例也会被销毁。

以上为vue生命周期内容,如果有哪里写错了,欢迎各位大佬指正,谢谢大家!

posted @ 2021-09-07 15:49  小吴3  阅读(5951)  评论(0编辑  收藏  举报