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。

要更加努力呀,加油~
相关文章
|
3天前
|
JavaScript
Vue中如何设置在执行删除等危险操作时给用户提示(二次确认后执行对应的操作)
这篇文章介绍了在Vue项目中如何实现执行删除等危险操作时的二次确认机制,使用Element UI的`el-popconfirm`组件来弹出确认框,确保用户在二次确认后才会执行删除操作。
Vue中如何设置在执行删除等危险操作时给用户提示(二次确认后执行对应的操作)
|
3天前
|
JavaScript
如何创建一个Vue项目(手把手教你)
这篇文章是一篇手把手教读者如何创建Vue项目的教程,包括使用管理员身份打开命令行窗口、找到存放项目的位置、通过vue-cli初始化项目、填写项目信息、进入项目目录、启动项目等步骤,并提供了一些常见第三方库的引入方法。
如何创建一个Vue项目(手把手教你)
|
3天前
|
前端开发
StringBoot+Vue实现游客或用户未登录系统前、可以浏览商品等信息、但是不能购买商品或者加入购物车等操作。登录系统显示用户的登录名(源码+讲解)
这篇文章介绍了使用StringBoot+Vue实现用户登录状态判断的方法,包括前端加载用户信息和后端设置session的源码示例。
|
3天前
|
JavaScript
在Vue中使用Avue、配置过程以及实际应用
这篇文章介绍了作者在Vue项目中集成Avue组件库的完整过程,包括安装、配置和实际应用,展示了如何利用Avue实现动态表单和数据展示的功能。
在Vue中使用Avue、配置过程以及实际应用
|
3天前
|
JavaScript
如何在Vue页面中引入img下的图片作为背景图。../的使用
这篇文章介绍了在Vue页面中如何引入`img`目录下的图片作为背景图,提供了两种使用相对路径的方法。第一种是使用`../assets/img/`作为路径引入图片,第二种是使用`../../assets/img/`作为路径。文章还展示了使用这些方法的代码实现和效果展示,并鼓励读者学无止境。
如何在Vue页面中引入img下的图片作为背景图。../的使用
|
3天前
|
JavaScript
如何通过点击商品的信息(图片或者文字)跳转到更加详细的商品信息介绍(前后端分离之Vue实现)
该博客文章介绍了如何在Vue 2框架下实现前后端分离的商品信息展示和详情页跳转,包括排序筛选、详情展示、加入购物车和分享功能。
如何通过点击商品的信息(图片或者文字)跳转到更加详细的商品信息介绍(前后端分离之Vue实现)
|
3天前
|
JavaScript
在Vue中使用Swiper轮播图、同时解决点击轮播图左右切换按钮不生效的问题、同时将轮播图抽离出为一个公共组件
这篇文章介绍了在Vue中如何使用Swiper插件创建轮播图,解决Swiper左右切换按钮不生效的问题,并展示了如何将Swiper轮播图抽离成一个可复用的公共组件,同时提供了详细的安装、配置和优化建议。
在Vue中使用Swiper轮播图、同时解决点击轮播图左右切换按钮不生效的问题、同时将轮播图抽离出为一个公共组件
|
3天前
|
JavaScript
如何查看Vue使用的版本
这篇文章介绍了如何在项目中查看Vue及其相关库的版本信息,比如element-ui和element-china-area-data。要查看Vue的版本,需要查看项目中的`package.json`文件,在`dependencies`部分可以找到Vue的版本号。如果需要查询不同版本的兼容性,可以访问相应的官方文档或资源网站。
|
3天前
|
存储 JavaScript 前端开发
Vue中如何通过三元运算符来展示不同的操作
这篇文章讲述了在Vue中如何使用三元运算符结合v-if指令来根据订单的不同状态展示不同的操作按钮,例如在待发货状态显示退款按钮,在待付款或完成状态显示删除按钮。
|
3天前
|
JavaScript 开发者
在Vue中引入Message,弹窗提示错误信息
这篇文章讲述了在Vue CLI项目中如何处理异常,通过引入Message组件实现弹窗提示错误信息,帮助开发者排查和解决webpack等问题。