Vue都使用那么久了,还不了解它的生命周期吗✨

简介: 我记得尤大曾经说过,你看Vue源码干嘛?你使用Vue又不需要它的源码,你只需要会用就行了!但是我们得卷啊,不卷怎么脱颖而出😥,我还记得在今年的蓝桥杯群里,有一同届的还不知道哪个大学的哥们,已经在读Vue/React/Node的源码了.....作为小菜鸡的我看着大佬侃侃而谈,在群角落里瑟瑟发抖。
大家好,我是Ned👀,一个刚刚入门前端未满两年的大三小学生🌹

未来路还长🎉, 一起努力加油吧❤~

前言

我记得尤大曾经说过,你看Vue源码干嘛?你使用Vue又不需要它的源码,你只需要会用就行了!

但是我们得卷啊,不卷怎么脱颖而出😥,我还记得在今年的蓝桥杯群里,有一同届的还不知道哪个大学的哥们,已经在读Vue/React/Node的源码了.....作为小菜鸡的我看着大佬侃侃而谈,在群角落里瑟瑟发抖。

image.png

最近有在牛客上复习Vue的知识,整理出这篇文章,一是方便自己未来复习,二是希望能够帮助一些跟我一样的朋友们复习一边知识点,学习在什么时候都不晚。

这篇文章会讲到:

  • Vue的生命周期到底是什么
  • Vue生命周期的执行顺序
  • 生命周期的每个阶段适合做什么
  • 我们的请求放在哪个生命周期会更合适
当然我只会讲我理解的emm,可能会很浅,还请多包涵。

Vue的生命周期到底是什么?

与其说是Vue的生命周期,我觉得不如说是其内组件的生命周期。
简单来说,它的生命周期就是用来描述一个组件从引入到退出的全过程。
那复杂来说呢?就是一个组件从创建开始经历了数据初始化挂载更新等步骤后,最后被销毁

Vue生命周期的执行顺序

他整体是分为三个大阶段的,在三个大阶段中,有细分为若干的小阶段。我们可以在不同的阶段去做不同的事情,后文也会讲到不同的阶段适合我们去做具体什么事情的。
image.png
我们先来看看它的执行顺序吧:

有两种方法,一种就是Vue的官方文档上面有一个图是专门解释生命周期的,但鉴于可能许多小伙伴们都是跟我一样,看英文文档都要伴随着翻译的水平,所以特意在网上找了个翻译过后的汉化版,放在这里给大家做参考:

生命周期.webp
这个图详细的解释了一个Vue实例从创建到销毁的全过程。

第二种方法,就是我们在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.dir(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)); //undefined
        console.dir(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.dir(this.$el)
        console.log("%c%s", "color:red", "data   : " + this.$data); //已被初始化
        console.dir(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);
        console.dir(this.$el)
        console.log("%c%s", "color:red", "data   : " + this.$data);
        console.dir(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);
        console.dir(this.$el)
        console.log("%c%s", "color:red", "data   : " + this.$data);
        console.dir(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.dir(this.$el)
        console.log("%c%s", "color:red", "data   : " + this.$data);
        console.dir(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.dir(this.$el)
        console.log("%c%s", "color:red", "data   : " + this.$data);
        console.dir(this.$data)
        console.log("%c%s", "color:red", "message: " + this.message)
    }

挂载阶段

其实这个代码的先后顺序就是他执行的先后顺序了,为了能有更新的状态,所以我找了个todolist的demo,可以添加跟删除的,方便我们来看,首先是刚进入页面:

image.png
我们可以看到beforeCreate是最先的,并且在此时的状态下,我们打印的信息什么都拿不到。

之后进入了created状态,在这个状态中我们的el,也就是Dom元素依旧是拿不到的,但是我们已经可以拿到data了,这意味着 created已经将数据加载进来了 ,已经为这个Vue实例开辟了内存空间。

beforeMount,挂载前状态,在我的理解挂载就是将虚拟Dom转变成真实Dom的过程,所以在这之前,我们的el当然还是拿不到的。

mounted,挂载结束,意味着虚拟Dom已经挂载在了真实的元素上,所以从此开始我们就可以拿到el了。我们可以用console.dir去打印一些我们需要的元素的属性。

至此,我们的挂载阶段就结束了。

更新阶段

下面我们删除一个list,来看一下更新状态。

更新状态.gif

每当我们去改变页面元素的时候,就会进入更新阶段,也就是beforeUpdate,updated这两个状态。

销毁阶段

下面我们再来看一下最后的销毁阶段。

销毁状态.gif

beforeDestroy,销毁前状态,在销毁之前,所以我们的元素、data都是如同挂载之后的阶段一样,都是可以打印出来的。

destroyed,其实最让我震惊的是这个,销毁完成的状态,我以为销毁了,那应该什么都打印不出来了,其实不然,他还是什么都可以打印出来的。

beforeDestroydestroyed,都是我们离开这个组件才会被调用的生命周期。

生命周期的每个阶段适合做什么

下面我们来讲讲,在不同的阶段我们可以做些什么:

created:
在Vue实例创建完毕状态,我们可以去访问data、computed、watch、methods上的方法和数据,但现在还没有将虚拟Dom挂载到真实Dom上,所以我们在此时访问不到我们的Dom元素(el属性,ref属性此时都为空)。

我们在此时可以进行一些简单的Ajax,并可以对页面进行初始化之类的操作

beforeMount:
它是在挂载之前被调用的,会在此时去找到虚拟Dom,并将其编译成Render

mounted:
虚拟Dom已经被挂载到真实Dom上,此时我们可以获取Dom节点,$ref在此时也是可以访问的。

我们在此时可以去获取节点信息,做Ajax请求,对节点做一些操作

beforeupdate:
响应式数据更新的时候会被调用,beforeupdate的阶段虚拟Dom还没更新,所以在此时依旧可以访问现有的Dom。

我们可以在此时访问现有的Dom,手动移除一些添加的监听事件

updated:
此时补丁已经打完了,Dom已经更新完毕,可以执行一些依赖新Dom的操作。

但还是不建议在此时进行数据操作,避免进入死循环(这个坑我曾经踩过)

beforeDestroy:
在Vue实例销毁之前被调用,在此时我们的实例还未被销毁。

在此时可以做一些操作,比如销毁定时器,解绑全局事件,销毁插件对象等

父子组件的生命周期

刚刚说的都是单页面,那么父子组件的生命周期会是什么样子呢?我们仅做一个简单的补充。

不知道大家在刚刚的图中是否注意到了这两行:

image.png

我们页面中的小li就是一个被嵌入在这个大页面内部的一个子组件,我们也打印了它的生命周期:

created() {
        console.log('list created')
    },
    mounted() {
        console.log('list mounted')
    },
    beforeUpdate() {
        console.log('list before update')
    },
    updated() {
        console.log('list updated')
    },
    beforeDestroy() {
        // 及时销毁,否则可能造成内存泄露
        console.log('list beforeDestroy')
    },
    destroyed(){
        console.log('list Destroy')
    }

由此可得,在父组件挂载前阶段,子组件已经挂载完成了。

不光是挂载阶段,其他两个阶段我们也可以打印出来,但是在这里我就不细说了,直接上结论:

  • 挂载阶段:父组件 beforeMount -> 子组件 created -> 子组件 mounted -> 父组件 mounted
  • 更新阶段:父组件 beforeUpdate -> 子组件 beforeUpdate -> 子组件 updated -> 父组件 updated
  • 销毁阶段:父组件 beforeDestroy -> 子组件 beforeDestroy -> 子组件 destroyed -> 父组件 destroyed

我们的请求放在哪个生命周期会更合适

那么至此我们已经对于Vue的生命周期有了一个基本的了解,现在我们来说一说,我们的请求应该放到哪个生命周期中才最为合适。

一般来说,会有两种回答:createdmounted
上文已经讲了,这两个回答,前者是数据已经准备好了,后者是连dom也已经加载完成了,那么到底哪个才是正确答案呢?

其实,两个都是可以的,但是mounted会更好。

可能有人会说: created的时间会更早,早些调用不是会省很多时间吗?这样性能会不会更高一点

别急,我们一点一点来看

  • 首先,它确实是早了,但是早不了几微秒,所以这其实没有提高性能
  • 其次,我们在created阶段并没有去做渲染,所以在接下来我们会去做Dom渲染,但是如果此时我们还做了Ajax操作,在Ajax结束之后就会返回数据,我们就会将其插入到主线程中去运行,去处理数据,但是我们要知道,在浏览器机制中,渲染线程跟js线程是互斥的,所以有可能我们做渲染的同时,另一边可能要处理Ajax返回的数据了,这时候渲染就有可能被打断,在处理完数组后,去进行重新渲染。

那如果在created中有多个Ajax呢?我们又要重新进行渲染,所以在created去做Ajax请求这明显不太合适。

  • 还有,有的时候我们接到返回的数据的时候可能要在回调函数中去进行一些Dom的操作,可是created阶段我们还没有将真实Dom加载出来,所以相对而言我们还是在mounted去调用要好一些
如果是服务端渲染,我们将其放入 created中进行,因为服务端不支持 mounted

写在最后

Vue算是前端学习旅途上陪伴我最长的东西了,但是至今还是没有将其学明白hhhh。

要更加努力呀,加油~
相关文章
|
5天前
|
缓存 JavaScript 前端开发
vue学习第四章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中计算属性的基本与复杂使用、setter/getter、与methods的对比及与侦听器的总结。如果你觉得有用,请关注我,将持续更新更多优质内容!🎉🎉🎉
vue学习第四章
|
5天前
|
JavaScript 前端开发
vue学习第九章(v-model)
欢迎来到我的博客,我是瑞雨溪,一名热爱JavaScript与Vue的大一学生,自学前端2年半,正向全栈进发。此篇介绍v-model在不同表单元素中的应用及修饰符的使用,希望能对你有所帮助。关注我,持续更新中!🎉🎉🎉
vue学习第九章(v-model)
|
4天前
|
JavaScript 前端开发 开发者
vue学习第十章(组件开发)
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文深入讲解Vue组件的基本使用、全局与局部组件、父子组件通信及数据传递等内容,适合前端开发者学习参考。持续更新中,期待您的关注!🎉🎉🎉
vue学习第十章(组件开发)
|
10天前
|
JavaScript 前端开发
如何在 Vue 项目中配置 Tree Shaking?
通过以上针对 Webpack 或 Rollup 的配置方法,就可以在 Vue 项目中有效地启用 Tree Shaking,从而优化项目的打包体积,提高项目的性能和加载速度。在实际配置过程中,需要根据项目的具体情况和需求,对配置进行适当的调整和优化。
|
10天前
|
存储 缓存 JavaScript
在 Vue 中使用 computed 和 watch 时,性能问题探讨
本文探讨了在 Vue.js 中使用 computed 计算属性和 watch 监听器时可能遇到的性能问题,并提供了优化建议,帮助开发者提高应用性能。
|
10天前
|
存储 缓存 JavaScript
如何在大型 Vue 应用中有效地管理计算属性和侦听器
在大型 Vue 应用中,合理管理计算属性和侦听器是优化性能和维护性的关键。本文介绍了如何通过模块化、状态管理和避免冗余计算等方法,有效提升应用的响应性和可维护性。
|
10天前
|
存储 缓存 JavaScript
Vue 中 computed 和 watch 的差异
Vue 中的 `computed` 和 `watch` 都用于处理数据变化,但使用场景不同。`computed` 用于计算属性,依赖于其他数据自动更新;`watch` 用于监听数据变化,执行异步或复杂操作。
|
10天前
|
JavaScript 前端开发 UED
vue学习第二章
欢迎来到我的博客!我是一名自学了2年半前端的大一学生,熟悉JavaScript与Vue,目前正在向全栈方向发展。如果你从我的博客中有所收获,欢迎关注我,我将持续更新更多优质文章。你的支持是我最大的动力!🎉🎉🎉
|
11天前
|
存储 JavaScript 开发者
Vue 组件间通信的最佳实践
本文总结了 Vue.js 中组件间通信的多种方法,包括 props、事件、Vuex 状态管理等,帮助开发者选择最适合项目需求的通信方式,提高开发效率和代码可维护性。
|
10天前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript和Vue的大一学生。自学前端2年半,熟悉JavaScript与Vue,正向全栈方向发展。博客内容涵盖Vue基础、列表展示及计数器案例等,希望能对你有所帮助。关注我,持续更新中!🎉🎉🎉