您的位置:首页 > 教程 > JavaScript > vue2与vue3中生命周期执行顺序的区别说明

vue2与vue3中生命周期执行顺序的区别说明

2022-06-29 15:56:30 来源:易采站长站 作者:

vue2与vue3中生命周期执行顺序的区别说明

目录
vue2与vue3中生命周期执行顺序区别生命周期比较简单例子说明三种情况下的生命周期执行顺序1、单页面下生命周期顺序2、父子、兄弟组件的生命周期顺序3、不同页面跳转时各页面生命周期的执行顺序

vue2与vue3中生命周期执行顺序区别

生命周期比较

    vue2中执行顺序>beforeCreate=>created=>beforeMount =>mounted=>beforeUpdate =>updated=>beforeDestroy=>destroyedvue3中执行顺序 setup=>onBeforeMount=>onMounted=>onBeforeUpdate=>onUpdated=>onBeforeUnmount=>onUnmounted

    对应关系

    vue2->vue3

      beforeCreate->setupcreated -> setupbeforeMount -> onBeforeMountmounted -> onMountedbeforeUpdate -> onBeforeUpdateupdated -> onUpdatedbeforeDestroy -> onBeforeUnmountdestroyed -> onUnmounted

      其中 vue3中的setup相当于vue2中beforeCreate 与created 但是的执行在beforeCreate 与created之前,所以setup无法使用 data 和 methods 中的数据和方法,即无法操作this,setup中的this等于 undefined,又因为setup中创建的变量与方法最后都要通过return返回出去,所以setup中的程序只能是同步的,而不能是异步,除非return 后面只接受一个异步对象,对象返回setup内定义的变量与方法,然后父组件使用Suspense标签包裹异步组件;

      vue3中 如果要使用vue2的beforeDestroy与destroyed需要把名称分别改为beforeUnmount,unmounted

      如果vue3中同时使用了vue2的写法,vue3的写法会优先执行;

      简单例子说明

      父组件App.vue

      <template>
        <h1>App父级组件</h1>
        <button @click="childShow = !childShow">切换child子组件的显示</button>
        <hr />
        <child v-if="childShow" />
      </template>
      <script lang="ts">
      import { defineComponent, reactive, ref } from "vue";
      //引入子组件
      import child from "./components/child.vue";
      export default defineComponent({
        name: "App",
        components: {
          child,
        },
        setup() {
          const childShow = ref(true);
          return {
            childShow,
          };
        },
      });
      </script>
      <style>
      * {
        margin: 0;
        padding: 0;
      }
      </style>

      子组件child.vue

      <template>
        <h2>child 子级组件</h2>
        <h3>{{ name }}</h3>
        <button @click="updateName">更新name</button>
      </template>
      <script lang="ts">
      import {
        defineComponent,
        onBeforeMount,
        onMounted,
        onBeforeUpdate,
        onUpdated,
        onBeforeUnmount,
        onUnmounted,
        ref,
      } from "vue";
      export default defineComponent({
        name: "child",
        //vue2中的生命周期钩子
        beforeCreate() {
          console.log("vue2 中的生命周期 beforeCreate");
        },
        created() {
          console.log("vue2 中的生命周期 created");
        },
        beforeMount() {
          console.log("vue2 中的生命周期 beforeMount");
        },
        mounted() {
          console.log("vue2 中的生命周期 mounted");
        },
        beforeUpdate() {
          console.log("vue2 中的生命周期 beforeUpdate");
        },
        updated() {
          console.log("vue2 中的生命周期 updated");
        },
        // vue2中的 beforeDestroy与 destroyed已经改名 无法使用
        beforeUnmount() {
          console.log("vue2 中的生命周期 beforeDestroy(beforeUnmount)");
        },
        unmounted() {
          console.log("vue2 中的生命周期 destroyed(unmounted)");
        },
        setup() {
          console.log("vue3中的setup");
          const name = ref("hhh");
          const updateName = () => {
            name.value += "6……6………6";
          };
          onBeforeMount(() => {
            console.log("vue3 中的生命周期 onBeforeMount");
          });
          onMounted(() => {
            console.log("vue3 中的生命周期 onMounted");
          });
          onBeforeUpdate(() => {
            console.log("vue3 中的生命周期 onBeforeUpdate");
          });
          onUpdated(() => {
            console.log("vue3 中的生命周期 onUpdated");
          });
          onBeforeUnmount(() => {
            console.log("vue3 中的生命周期 onBeforeUnmount");
          });
          onUnmounted(() => {
            console.log("vue3 中的生命周期 onUnmounted");
          });
          return {
            name,
            updateName,
          };
        },
      });
      </script>
      

      运行起来的显示效果

      进入页面 按f12 打开调试 刷新页面

      可以看出vue3中

        setup执行在beforeCreate与created前面;onBeforeMount执行在beforeMount前面;onMounted执行在mounted前面;

        点击 更新name

        可以看出vue3中

          onBeforeUpdate执行在beforeUpdate前面;onUpdated执行在updated前面;点击 切换child子组件的显示

          可以看出vue3中

            onBeforeUnmount执行在beforeDestroy前面;onUnmounted执行在destroyed前面;

            三种情况下的生命周期执行顺序

            生命周期:在创建一个vue实例时,会经历一系列的初始化过程(Vue实例从创建到销毁的过程),这个过程就是vue的生命周期。

            Vue提供给开发者的一系列的回调函数,方便我们添加自定义的逻辑,Vue的生命周期从创建到销毁,重要的节点挂载数据更新。

              创建阶段>挂载渲染页面阶段 beforeMount、mounted更新阶段 beforeUpdate、updated卸载阶段 beforeDestory、destoryed

              1、单页面下生命周期顺序

              献上一波代码,看下各周期钩子函数的执行顺序:

              <!DOCTYPE html>
              <html lang="en">
              <head>
              	<meta charset="UTF-8">
              	<meta name="viewport" content="width=device-width, initial-scale=1.0">
              	<meta http-equiv="X-UA-Compatible" content="ie=edge">
              	<title>vue生命周期学习</title>
              	<script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script>
              </head>
              <body>
              <div id="app">
              	<h1>{{message}}</h1>
              </div>
              </body>
              <script>
                  var vm = new Vue({
                      el: '#app',
                      data: {
                          message: 'Vue的生命周期'
                      },
                      beforeCreate: function() {
                          console.group('------beforeCreate创建前状态------');
                          console.log("%c%s", "color:red" , "el     : " + this.$el); //undefined
                          console.log("%c%s", "color:red","data   : " + this.$data); //undefined
                          console.log("%c%s", "color:red","message: " + this.message)
                      },
                      created: function() {
                          console.group('------created创建完毕状态------');
                          console.log("%c%s", "color:red","el     : " + this.$el); //undefined
                          console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
                          console.log("%c%s", "color:red","message: " + this.message); //已被初始化
                      },
                      beforeMount: function() {
                          console.group('------beforeMount挂载前状态------');
                          console.log("%c%s", "color:red","el     : " + (this.$el)); //已被初始化
                          console.log(this.$el);
                          console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
                          console.log("%c%s", "color:red","message: " + this.message); //已被初始化
                      },
                      mounted: function() {
                          console.group('------mounted 挂载结束状态------');
                          console.log("%c%s", "color:red","el     : " + this.$el); //已被初始化
                          console.log(this.$el);
                          console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
                          console.log("%c%s", "color:red","message: " + this.message); //已被初始化
                      },
                      beforeUpdate: function () {
                          console.group('beforeUpdate 更新前状态===============》');
                          console.log("%c%s", "color:red","el     : " + this.$el.innerHTML);
                          console.log(this.$el);
                          console.log("%c%s", "color:red","data   : " + this.$data);
                          console.log("%c%s", "color:red","message: " + this.message);
                      },
                      updated: function () {
                          console.group('updated 更新完成状态===============》');
                          console.log("%c%s", "color:red","el     : " + this.$el.innerHTML);
                          console.log(this.$el);
                          console.log("%c%s", "color:red","data   : " + this.$data);
                          console.log("%c%s", "color:red","message: " + this.message);
                      },
                      beforeDestroy: function () {
                          console.group('beforeDestroy 销毁前状态===============》');
                          console.log("%c%s", "color:red","el     : " + this.$el);
                          console.log(this.$el);
                          console.log("%c%s", "color:red","data   : " + this.$data);
                          console.log("%c%s", "color:red","message: " + this.message);
                      },
                      destroyed: function () {
                          console.group('destroyed 销毁完成状态===============》');
                          console.log("%c%s", "color:red","el     : " + this.$el);
                          console.log(this.$el);
                          console.log("%c%s", "color:red","data   : " + this.$data);
                          console.log("%c%s", "color:red","message: " + this.message)
                      }
                  })
              </script>
              </html>
              

              (1)创建阶段:初始化事件,进行数据的观测

                new Vue({}) 创建一个空的实例对象,这个对象上只有生命周期函数和一些默认事件在beforeCreate时,$el和data都未初始化created 执行,完成了对data的初始化,通过编译将 template 模板转换成渲染函数( render ) ,执行渲染函数就可以得到一个虚拟节点树(内存中)先检查 template是否存在 如果存在模板编译成render函数,没有将外部html作为模板渲染。综合排名优先级:render函数选项 > template选项 > outer HTML.

                (2)挂载阶段

                  为vue实例添加$el成员,替换挂载的DOM成员其中在beforeMount时,初始化el和data,但el和data,但el和data,但el还是使用{{message}}进行占位mounted执行时,将message的值进行渲染

                  (3)更新阶段:触发对应组件的重新渲染

                    data 被改变时触发生命周期函数 beforeUpdate 执行,data是最新的,页面还未更新(旧的页面)根据最新的 data 重新渲染虚拟 DOM,并挂载到页面上,完成 Model 到 View 的更新updated 执行,此时 data 和页面都是最新的

                    (4)销毁阶段

                      beforeDestroy钩子函数在实例销毁之前调用。在这一步,实例仍然完全可用。destroyed钩子函数在Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

                      2、父子、兄弟组件的生命周期顺序

                      <template>
                      	<div class="father">
                      		<component-A class="son_A"></component-A>
                      		<component-B class="son_B"></component-B>
                      	</div>
                      </template>
                      // script部分同上代码,不多写了。

                      主要可以从以下几种情况分析:

                      (1)创建过程:

                      父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted

                      (2)组件的内部更新:

                      子组件的内部更新过程是:子beforeUpdate->子updated

                      同理父组件的内部更新过程也是:父beforeUpdate->父updated

                      (3)组件之间的更新:

                      当子组件使用emit修改父组件状态时,刚好这个状态又绑定在子组件的props上,更新过程是:父beforeUpdate->子beforeUpdate->子updated->父updated

                      (4)父子组件销毁:

                      父组件被销毁时子组件也同时被销毁,销毁的钩子过程是:父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

                      父子组件完整的生命周期图如下所示:

                        从上图可以看出,在父兄子组件挂载前,各组件的实例已经初始化完成。子组件挂载完成后,父组件还未挂载。所以组件数据回显的时候,在父组件mounted中获取api的数据,子组件的mounted是拿不到的。仔细看看父子组件生命周期钩子的执行顺序,会发现created这个钩子是按照从外内顺序执行,所以回显场景的解决方案是:在created中发起请求获取数据,依次在子组件的created中会接收到这个数据。Vue父子组件生命周期钩子的执行顺序遵循:从外到内,然后再从内到外,不管嵌套几层深,也遵循这个规律。

                        3、不同页面跳转时各页面生命周期的执行顺序

                        跳转不同页面和part2是相同的原理,从第一个页面(index)跳转到下一个页面(secondIndex)时,回先初始化secondIndex,之后在执行index页面的销毁阶段,最后secondIndex挂载完成.

                        题外话:

                        在开发过程中,通过对整个生命周期的了解,就可以很清晰地知道可以在什么阶段做什么事,或者某一操作应该在什么阶段执行

                        例如在create中进行数据操作,在mounted中进行DOM完成后的操作,在destroyed进行事件解绑和功能注销

                        当然,对于组件间、不同页面跳转的生命周期顺序也应该更加了解,避免页面渲染数据错误或根本拿不到数据等情况

                        总结来说就是在合适的时机做对的事情,才能事半功倍嘛~

                        以上为个人经验,希望能给大家一个参考,也希望大家多多支持易采站长站。

                        如有侵权,请联系QQ:279390809 电话:15144810328

相关文章

  • vue跳转页面的几种方法(推荐)

    vue跳转页面的几种方法(推荐)

    vue跳转不同页面的多种方法 1:router-link跳转 !-- 直接跳转 --router-link to='/testDemo' button点击跳转2/button/router-link !-- 带参数跳转 --router-link :to="{path:'testDemo',query:{setid:123456}}" button点击跳转
    2020-03-26
  • Vue+elementUI实现多图片上传与回显功能(含回显后继续上传或删除

    Vue+elementUI实现多图片上传与回显功能(含回显后继续上传或删除

    最近有使用vue+elementUI实现多图片上传的需求,遂做此纪录。 本次主要写一下前端的实现细节,至于后台以Multipart[ ]数组接收即可,不再赘述,网上一搜大把文章可供参考。 本次使用
    2020-03-23
  • 微信小程序搜索框样式并实现跳转到搜索页面(小程序搜索功能

    微信小程序搜索框样式并实现跳转到搜索页面(小程序搜索功能

    上效果图: 一:搜索框功能实现 1.在首页做一个搜索框的样式并实现跳转到搜索页面 view class='page_row' bindtap="suo" view class="search" view class="df search_arr" icon class="searchcion" size='20' type='search'/
    2020-03-10
  • 微信小程序实现canvas分享朋友圈海报

    微信小程序实现canvas分享朋友圈海报

    本文实例为大家分享了微信小程序分享朋友圈海报的具体代码,供大家参考,具体内容如下 思路:生成朋友圈海报放在公共文件,首先需要绘制canvas,点击分享朋友圈按钮,在手机屏幕
    2020-06-21
  • 详解ES6 Modules

    详解ES6 Modules

    当下, 我们几乎所有的项目都是基于 webpack、rollup 等构建工具进行开发的,模块化已经是常态。 我们对它并不陌生,今天,我们就再系统的回顾一下ES6的模块机制, 并总结下常用的操
    2020-07-04
  • Vue-router 报错NavigationDuplicated的解决方法

    Vue-router 报错NavigationDuplicated的解决方法

    版本:3.1.x 报错原因: 使用push()、replace()进行导航时,不能重复导航到当前路由。 解决办法: 方法1:在定义路由的文件中router/index.js const originalPush = VueRouter.prototype.pushVueRouter.protot
    2020-03-31
  • vue使用better-scroll实现滑动以及左右联动

    vue使用better-scroll实现滑动以及左右联动

    本文实例为大家分享了vue实现滑动以及左右联动效果的具体代码,供大家参考,具体内容如下 一、首先需要在项目中引入better-scroll 1. 在package.json 直接写入 "better-scroll":"^1.15.1" 版本以
    2020-06-30
  • Vue如何提升首屏加载速度实例解析

    Vue如何提升首屏加载速度实例解析

    在Vue项目中,引入到工程中的所有js、css文件,编译时都会被打包进vendor.js,浏览器在加载该文件之后才能开始显示首屏。若是引入的库众多,那么vendor.js文件体积将会相当的大,影响
    2020-06-25