Vue2 生命周期


🔗 Vue3 生命周期

生命周期钩子Vue 2Vue 3 (Composition API)备注
创建前beforeCreate无直接对应在数据观测和初始化事件/侦听器之前调用
创建后createdsetup实例已被创建,完成数据观测,但尚未挂载
挂载前beforeMountonBeforeMount`在挂载开始之前被调用
挂载后mountedonMounted实例被挂载后调用
更新前beforeUpdateonBeforeUpdate数据更新时调用,发生在虚拟 DOM 打补丁之前
更新后updatedonUpdated由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子
卸载前beforeDestroyonBeforeUnmount实例销毁之前调用。在这一步,实例仍然完全可用
卸载后destroyedonUnmountedVue 实例销毁后调用。调用后,所有的事件监听器都会被移除,所有的子实例也都会被销毁
激活时activatedonActivatedkeep-alive 组件激活时调用
失活时deactivatedonDeactivatedkeep-alive 组件停用时调用
错误捕获errorCapturedonErrorCaptured当捕获一个来自子孙组件的错误时被调用

Vue2 生命周期

  1. beforeCreate:创建之前eldatamessage都还是undefined,不可用的)
  2. created:创建完毕(能读取到数据data的值,但是DOM还没生成)
  3. beforeMount:挂载之前(生成DOM,但此时{{ message }}还没有挂载data中的数据)
  4. mounted:挂载完毕{{ message }}已经成功挂载渲染data的值)
  5. beforeUpdate:更新之前
  6. updated:更新完毕
  7. beforeDestroy:销毁之前
  8. destroyed:销毁完毕(实例与视图的关系解绑,再修改message的值,视图再也不会更新了)
  9. activated:keep-alive 组件激活时调用
  10. deactivated:keep-alive 组件停用时调用

注:

  • activateddeactivated 是比较特殊的两个钩子,需要keep-live配合使用
  • 当引入 keep-alive 的时候,页面第一次进入,钩子的触发顺序 created => mounted => activated,退出时触发 deactivated。当再次进入(前进或者后退)时,只触发activated

在这里插入图片描述

举例代码:

<body>
    <div id="app">
        {{ message }}
    </div>

    <script>
        let app = new Vue({
            el: "#app",
            data: {
                message: 'xia',
            },
            beforeCreate() {
                console.group("1. beforeCreate() =====> 创建之前");
                console.log("%c%s", "color:red", "el     : " + this.$el);
                console.log("%c%s", "color:red", "data   : " + this.$data);
                console.log("%c%s", "color:red", "message: " + this.message);
                console.log("%c%s", "color:red", "el、data和message都还是undefined,不可用的");
                console.log("-------------------------------------------");
            },
            created() {
                console.group("2. created() =====> 创建完毕");
                console.log("%c%s", "color:red", "el     : " + this.$el);
                console.log("%c%s", "color:red", "data   : " + this.$data);
                console.log("%c%s", "color:red", "message: " + this.message);
                console.log("%c%s", "color:red", "能读取到数据data的值,但是DOM还没生成");
                console.log("-------------------------------------------");
            },
            beforeMount() {
                console.group("3. 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);
                console.log("%c%s", "color:red", "生成DOM,但此时{{ message }}还没有挂载data中的数据");
                console.log("-------------------------------------------");
            },
            mounted() {
                console.group("4. 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);
                console.log("%c%s", "color:red", "{{ message }}已经成功挂载渲染data.name的值:Xia");
                console.log("-------------------------------------------");
            },
            beforeUpdate() {
                console.group("5. beforeUpdate() =====> 更新之前");
                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);
                console.log("-------------------------------------------");
            },
            updated() {
                console.group("6. beforeUpdate() =====> 更新完毕");
                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);
                console.log("-------------------------------------------");
            },
            beforeDestroy() {
                console.group("7. 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);
                console.log("-------------------------------------------");
            },
            destroyed() {
                console.group("8. 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);
                console.log("%c%s", "color:red", "实例与视图的关系解绑,再修改message的值,视图再也不会更新了");
                console.log("-------------------------------------------");
            }
        });
    </script>
</body>

create 和 mounted

beforecreated:Vue 实例的挂载元素$el 和 数据对象data 并未初始化

created:完成了 data 数据的初始化,$el没有
beforeMount:完成了 $el 和 data 初始化,但还是挂载在虚拟的 DOM 节点上
mounted :Vue 实例挂载到实际的 DOM 上
.
另外在标红处,我们能发现 $el还是 {{message}},这里就是应用的 Virtual DOM(虚拟Dom)技术,先把坑占住了,到后面mounted挂载的时候再把值渲染进去

这里写图片描述


update

这里我们在 chrome console里执行以下命令

app.message = 'bing'

下面就能看到data里的值被修改后,将会触发update的操作。
这里写图片描述


destroy

这里我们在console里执行下命令对 vue实例进行销毁

app.$destroy();

销毁完成后,我们再重新改变message的值,vue不再对此动作进行响应了。但是原先生成的dom元素还存在,执行了destroy操作,后续就不再受vue控制了。
这里写图片描述


activated

比较特殊的一个钩子,需要keep-live配合使用

activated:动态组件初始化渲染过程中调用 keep-alive组件激活时调用。
deactivated:动态组件移出过程中调用 keep-alive组件停用时调用。

当引入 keep-alive 的时候,页面第一次进入,钩子的触发顺序 created => mounted => activated,退出时触发 deactivated。当再次进入(前进或者后退)时,只触发activated

keep-alive 之后页面模板第一次初始化解析变成HTML片段后,再次进入就不在重新解析而是读取内存中的数据,即,只有当数据变化时,才使用VirtualDOM进行diff更新。故,页面进入的数据获取应该在activated中也放一份。数据下载完毕手动操作DOM的部分也应该在activated中执行才会生效。

所以,应该activated中留一份数据获取的代码,或者不要created部分,直接将created中的代码转移到activated中。


⚡️Vue2 生命周期总结

1. beforecreate

执行时组件实例还未创建,并未初始化

  • data:未被创建,值为 undefined

  • el:未被创建,值为 undefined

  • this:指向创建的实例,但不能访问到 data、computed、watch、methods 上的方法和数据

一般用于设置title、keywords等。

.

2. created

组件初始化完毕,各种数据可以使用,处于未挂载阶段

  • data:完成了初始化,可以访问和修改其中的属性。

  • el:仍然不可用,组件尚未被挂载到 DOM 中

  • this:指向组件实例,可以访问组件实例上的所有属性和方法:this.data 可以访问,watcher、event 和 methods 也已经可用。

组件首次访问data、methods等;一般用于数据初始化、ajax请求。

.

3. beforeMount

  • data:完成了初始化,可以访问和修改其中的属性。

  • el:完成了初始化,但尚未挂载到真实 DOM,还没有被渲染成最终的 DOM 结构,因此不能访问到真实的 DOM 元素,el 属性仅是虚拟的元素节点。

  • this:指向的是 Vue 组件的实例。可以通过 this 访问组件实例上的所有属性和方法,包括响应式数据、计算属性、方法、事件等。由于组件实例已经完成了数据观测等初始化工作,因此 this 上的数据和方法都是可用的。就不是能用来获取DOM~

用来做一些初始化的工作,例如从服务器加载数据、进行一些计算或者准备一些其他的操作。

.

4. mounted

  • data:完成了初始化,可以访问和修改其中的属性。

  • el:完成了 DOM 元素的挂载,已经可以进行 DOM 操作。

  • this:指向的是 Vue 组件的实例。可以通过 this 访问组件实例上的所有属性和方法。包括对DOM的操作

模板已经真实地挂载到了页面中,用户已经可以看到渲染好的页面了。
这时可以操作 DOM、发送请求、初始化或使用其他第三方库等

.

5. beforeUpdate

更新前,在组件的响应式数据发生变化,并且由此导致的虚拟 DOM 重新渲染和打补丁(patching),即将应用于真实 DOM 之前被调用

当组件的状态即将更新,但尚未反映到 DOM 上时,这个钩子会被触发。因此还不能访问到更新后的 DOM。

  • data:数据已经是最新的,但还没有触发视图的重新渲染。因此,此时你可以访问到更新后的数据值。

  • el:仍然指向旧的 DOM 元素,它还没有被更新以反映 data 中的新变化。
    这意味着,尽管 data 中的数据已经更新,但用户看到的页面内容还是旧的,因为新的 DOM 元素还没有被创建和挂载。

  • this:指向的是 Vue 组件的实例。可以通过 this 访问到组件实例上的所有属性和方法,包括已经更新的 data。
    尽管 this.data 反映了最新的数据状态,但实际的 DOM 元素(this.$el)还没有更新。

.

6. updated

更新后,在组件的虚拟 DOM 已经重新渲染和打补丁(patching)到真实的 DOM 之后被调用

当组件的响应式数据发生变化,并且这些变化已经反映到组件的视图上时,updated 钩子就会被触发。

这时可以访问到组件更新后的 DOM,也可以对更新后的状态进行操作,但应避免在该钩子中对状态进行修改,因为这可能会导致无限循环的更新。

  • data:数据已经是最新的,且视图已经重新渲染。

  • el:指向的 DOM 元素已经更新
    此时,用户看到的页面内容是与 data 中的数据保持一致的,可以通过 this.$el 访问到这个更新后的 DOM 元素,并进行后续的 DOM 操作或查询。

  • this:指向的是 Vue 组件的实例。可以访问到最新的数据和方法,并且 DOM 已经与最新的数据保持同步,因此你可以在 this 的上下文中执行依赖于最新 DOM 状态的操作。

.

7. beforeDestroy

组件实例即将被销毁,用于在组件实例销毁之前执行一些清理工作

这时可以执行如移除事件监听器、取消定时器、销毁子组件或执行其他必要的清理工作,防止内存泄漏

在 Vue 3 中,beforeDestroy 被重命名为 beforeUnmount

  • data:数据仍然是可以访问和使用的

  • el:指向的 DOM 元素仍然存在,并且与组件的当前状态相对应
    此时,你可以通过 this.$el 访问到这个 DOM 元素,并执行一些最后的 DOM 操作或查询

  • this:指向的是 Vue 组件的实例。仍可以访问组件实例上的所有属性和方法。

.

8. destroyed

组件实例已经被完全销毁,在组件实例已经被销毁和清理之后调用

此时Vue 实例上的所有东西都被销毁,所有的事件监听器会被移除。因此无法访问组件的任何状态或方法。该钩子在服务器端渲染期间不被调用。

主要用于执行一些不依赖于组件实例本身的清理工作,比如记录日志、发送统计信息等。

  • data:数据仍然可以被访问(如果你还持有组件实例的引用),但此时它们已经与 Vue 的响应式系统断开连接,不再具有响应性

  • el:指向的 DOM 元素已经被移除,不再与组件实例关联。

  • this:仍然指向组件实例,但由于组件已经被销毁,这个实例上的大多数方法和属性都已经不再有效。
    尤其是与响应式数据和 DOM 相关的属性和方法,如 this.data 和 this.$el,都将不再可靠。


示意图:

这里写图片描述


⚡️Vue2 父子组件生命周期执行顺序

1. 首次加载渲染过程

  1. 父beforeCreate
  2. 父created
  3. 父beforeMount
  4. 子beforeCreate
  5. 子created
  6. 子beforeMount
  7. 子mounted
  8. 子activated
  9. 父mounted

2. 父组件更新过程

  1. 父beforeUpdate
  2. 子deactivated
  3. 父updated

3. 子组件更新过程

  1. 父beforeUpdate
  2. 子beforeUpdate
  3. 子updated
  4. 父updated

4. 销毁过程

  1. 父beforeDestroy
  2. 子beforeDestroy
  3. 子destroyed
  4. 父destroyed

activated和deactivated只会在父组件中使用keep-alive时才会被调用。


keep-alive 中的生命周期

keep-alive是 Vue 提供的一个内置组件,用来对组件进行缓存——在组件切换过程中将状态保留在内存中,防止重复渲染DOM。

这意味着当组件再次被激活时,它将不会被重新渲染或重新初始化,而是保持其之前的状态和数据。这对于提高页面性能和用户体验特别有用,特别是当你需要在不同组件之间频繁切换时。

<keep-alive>  
  <component :is="currentComponent"></component>  
</keep-alive>

在上面的例子中,currentComponent 是一个变量,用于动态地确定当前要显示的组件。通过使用 keep-alive,你可以确保即使切换组件,它们的状态也会被保留。

  1. 条件渲染
    虽然 keep-alive 可以缓存组件实例,但它仍然需要组件被渲染。
    如果组件的条件渲染表达式(如 v-if)为 false,则组件不会被渲染,因此也不会被 keep-alive 缓存。

  2. 生命周期钩子
    当组件被 keep-alive 缓存时,其生命周期钩子函数的行为会发生变化:

    • 会多出两个生命周期:deactivated、activated

    • 当组件被切换出去时:beforeDestroy 和 destroyed 钩子不会被触发,因为组件不会被真正销毁。
      组件会被缓存到内存中,同时 deactivated 钩子会被调用

    • 当组件再次被激活时:activated 钩子会被调用,而不是 created 或 mounted。会从缓存里找组件

  3. 全生命周期

    • 首次进入:beforeCreate => created => beforeMount => mounted => activated
    • 离开组件:deactivated (不会触发 beforeDestroydestroyed 钩子)
    • 再次进入:activated (不会触发 beforeCreatecreatedbeforeMountmounted 钩子)
    • 组件被销毁:beforeDestroy => destroyed

数据请求在created和mouted的区别

created是在组件实例一旦创建完成的时候立刻调用,这时候页面dom节点并未生成;

mounted是在页面dom节点渲染完毕之后就立刻执行的。触发时机上created是比mounted要更早的
两者的相同点:都能拿到实例对象的属性和方法。

讨论这个问题本质就是触发的时机,放在mounted中的请求有可能导致页面闪动(因为此时页面dom结构已经生成),但如果在页面加载前完成请求,则不会出现此情况。建议对页面内容的改动放在created生命周期当中。

另外,SSR不支持 beforeMount 、mounted 钩子函数,放在 created 中有助于一致性。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫老板的豆

你的鼓励将是我创作的最大动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值