Vue组件(二)-生命周期函数

说到生命周期函数,就要来先谈谈生命周期,一个Vue实例从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、销毁等一系列过程,我们称之为Vue的生命周期
更通俗的说实例从被创建出来、运行、最后被销毁所要经历的一系列过程,就是生命周期。

在Vue生命周期的不同阶段,内部会自动执行一些称为生命周期钩子的函数,也称之为生命周期函数,也叫生命周期钩子,生命周期事件。

这些生命周期钩子可以在Vue的选项中配置,如下:

<div id="app">
  <input type="text" v-model="message">
  <button v-on:click="handleDestroy">销毁</button>
  <p>{{message}}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>
<script>
  let vm = new Vue({
    el: "#app",
    data: {
      message: 'Hello world',
    },
    methods: {
      handleDestroy() {
        this.$destroy();
      }
    },
    beforeCreate() {
      console.groupCollapsed("%c%s", "color:red", '1、实例创建之前: beforeCreate');
      console.log("$el:", this.$el,);
      console.log("$data:", this.$data);
      console.groupEnd();
    },
    created() {
      console.groupCollapsed("%c%s", "color:red", '2、实例创建完毕: created');
      console.log("$el:", this.$el);
      console.log("$data:", JSON.stringify(this.$data));
      console.groupEnd();
    },
    beforeMount() {
      console.groupCollapsed("%c%s", "color:red", '3、实例挂载之前: beforeMount');
      console.log("$el:", this.$el.innerHTML);
      console.log("$data:", JSON.stringify(this.$data));
      console.groupEnd();
    },
    mounted() {
      console.groupCollapsed("%c%s", "color:red", '4、实例挂载完毕: mounted');
      console.log("$el:", this.$el.innerHTML);
      console.log("$data:", JSON.stringify(this.$data));
      console.groupEnd();
    },
    beforeUpdate() {
      console.groupCollapsed("%c%s", "color:red", '5、实例更新之前: beforeUpdate');
      console.log("$el:", this.$el.innerHTML);
      console.log("$data:", JSON.stringify(this.$data));
      console.groupEnd();
    },
    updated() {
      console.groupCollapsed("%c%s", "color:red", '6、实例更新完毕:updated');
      console.log("$el:", this.$el.innerHTML);
      console.log("$data:", JSON.stringify(this.$data));
      console.groupEnd();
    },
    beforeDestroy() {
      console.groupCollapsed("%c%s", "color:red", '7、实例销毁之前:beforeDestroy');
      console.log("$el:", this.$el.innerHTML);
      console.log("$data:", JSON.stringify(this.$data));
      console.groupEnd();
    },
    destroyed() {
      console.groupCollapsed("%c%s", "color:red", '8、实例销毁完毕:destroyed');
      console.log("$el:", this.$el.innerHTML);
      console.log("$data:", JSON.stringify(this.$data));
      console.groupEnd();
    }
  });
</script>

上面的例子中,如果在生命周期的钩子函数中打断点观察调用栈和作用域,更容易理解Vue的生命周期,在生命周期钩子中我们看到Vue内部执行了很多方法,其结果是实例的this在不断的变化。


生命周期的三个阶段

一、创建阶段

1.初始化事件和生命周期

实例、组件通过new Vue() 创建出来之后会初始化事件和生命周期
完成后,就会执行beforeCreate钩子函数,这个时候,数据还没有挂载,无法访问到数据和真实的dom。
在这里插入图片描述

2. 初始化注入和校验

实例完成数据观测 (data observer), 属性和方法的运算,watch/event 事件回调。但挂载阶段还没开始,$el 属性目前不可见。
完成后,就会执行created钩子函数,created函数是最早能够调用data和methods数据的地方,更改数据不会触发其他的钩子函数,一般可以在这里获取初始数据。
在这里插入图片描述

3. 找实例或者组件对应的模板,编译模板为虚拟Dom放入到render函数中准备渲染

① 判断实例里是否有el选项

  • 存在el,实例将立即进入编译过程;
  • 不存在el,需要显式调用 vm.$mount() 手动开启编译。

② 判断实例里是否有template选项

  • 没有,将el挂载点的HTML作为template进行页面渲染;
  • 有,使用实例里面的template进行页面渲染

完成后,就会执行beforeMount钩子函数,这个函数中虚拟Dom已经创建完成,准备渲染,在这里也可以更改数据,不会触发数据更新钩子。
在这里插入图片描述
5. 开始render,渲染出真实dom
完成后,就会执行mounted钩子函数,这个时候,组件已经出现在页面中,数据、真实dom都已经处理好了,事件都已经挂载好了。
在这里插入图片描述

二、运行阶段

  1. 如果组件或实例的数据被更改,会立即执行beforeUpdate钩子函数,钩子函数执行后后Vue的虚拟Dom机制会重新构建虚拟Dom与上一次的虚拟Dom树利用diff算法进行对比之后重新渲染。
    在这里插入图片描述

  2. 当更新完成后,会执行updated钩子函数执行,此时数据已经更改完成,Dom也重新render完成。
    在这里插入图片描述

三、销毁阶段

  1. 当经调用$destroy方法后,立即执行beforeDestroy钩子。

  2. 销毁实例与DOM之间的关联,解绑它的全部指令及事件监听器(并不能清除已有的页面上的DOM),之后会执行destroyed钩子。
    在这里插入图片描述
    beforeDestroy和destroyed用法相似,一般在这里做善后工作,如清除计时器、清除非指令绑定的事件等等

PS:销毁实例与DOM之间的关联,解绑它的全部指令及事件监听器,并不能清除已有的页面上的DOM。
在这里插入图片描述
在这里插入图片描述

vue中父级与子组件生命周期的先后顺序

修改一下上面的例子,在实例中挂载一个子组件,通过这段代码来看一下父级与子组件生命周期的先后顺序

<div id="app">
  <input type="text" v-model="message">
  <button v-on:click="handleDestroy">销毁父组件</button>
  <button v-on:click="flag=!flag">销毁/重建子组件</button>
  <child-a :msg="message" inline-template v-if="flag">
    <div class="child-a">
      <label>{{msg}}</label><input type="text" v-model="title">
    </div>
  </child-a>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>
<script>
  let vm = new Vue({
    el: "#app",
    data: {
      message: '父组件信息',
      flag: true
    },
    methods: {
      handleDestroy() {
        this.$destroy();
      }
    },
    components: {
      'childA': {
        data() {
          return {
            title: '子组件',
          }
        },
        props: ['msg'],
        beforeCreate() {
          console.log("%c%s", "color:green", '(1)、子组件 beforeCreate');
        },
        created() {
          console.log("%c%s", "color:green", '(2)、子组件 created');
        },
        beforeMount() {
          console.log("%c%s", "color:green", '(3)、子组件 beforeMount');
        },
        mounted() {
          console.log("%c%s", "color:green", '(4)、子组件 mounted');
        },
        beforeUpdate() {
          console.log("%c%s", "color:green", '(5)、子组件 beforeUpdate');
        },
        updated() {
          console.log("%c%s", "color:green", '(6)、子组件 updated ');
        },
        beforeDestroy() {
          console.log("%c%s", "color:green", '(7)、子组件 beforeDestroy ');
        },
        destroyed() {
          console.log("%c%s", "color:green", '(8)、子组件 destroyed ');
        }
      }
    },
    beforeCreate() {
      console.log("%c%s", "color:red", '1、实例创建之前: beforeCreate');
    },
    created() {
      console.log("%c%s", "color:red", '2、实例创建完毕: created');
    },
    beforeMount() {
      console.log("%c%s", "color:red", '3、实例挂载之前: beforeMount');
    },
    mounted() {
      console.log("%c%s", "color:red", '4、实例挂载完毕: mounted');
    },
    beforeUpdate() {
      console.log("%c%s", "color:red", '5、实例更新之前: beforeUpdate');
    },
    updated() {
      console.log("%c%s", "color:red", '6、实例更新完毕:updated');
    },
    beforeDestroy() {
      console.log("%c%s", "color:red", '7、实例销毁之前:beforeDestroy');
    },
    destroyed() {
      console.log("%c%s", "color:red", '8、实例销毁完毕:destroyed');
    }
  });
</script>

1、当父组件执行完beforeMount,会依次执行子组件的生命周期钩子,直到全部子组件挂载到实例上(执行完子组件的mounted钩子),父组件才会进入mounted钩子。
在这里插入图片描述在这里插入图片描述
2、更新子组件的数据,不会触发父组件的生命周期钩子
3、如果子组件引用了父组件的数据,父组件数据更新时,执行顺序是:
在这里插入图片描述
4、销毁父组件时,同时销毁其包含的子组件,同前面说的一样,子组件的视图也不会消失
在这里插入图片描述
5、本例中,通过v-if的方法销毁子组件时,同时会触发父组件的更新钩子

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值