Vue生命周期,总也学不会,所以我详细整理了一下

news2024/11/25 16:27:57

今天,我和大家一起来对vue生命周期做一个整理和思考,希望有缘人看到我的年度整理和思考,如果觉得靠谱呢,就交个朋友,如果觉得我整理的不足,就请指出,让我们一起进步,让我们2023年能共同思考。

文本将进行3个小模块,第一呢是老生常谈,然后再结合我的理解,说一说,vue的生命周期有哪些,每个阶段做了一些什么事情 ,而项目中,我们可以做一些什么事情;

第二呢,说一下嵌套父子组件情况下,生命周期的执行顺序;

第三,整理后思考一下,created和mounted两个钩子之间的时间差,可能会受哪些因素的影响

 

目录

一、vue的生命周期 

1. 生命周期钩子函数

2. 常用的几个钩子

3. 为什么关掉组件,定时器还在执行?

二、父子组件生命周期执行顺序

1. 嵌套一个子组件

2. 查看执行顺序

三、created和mounted之间的时间差,影响因素有哪些?

1.  beforeMounted

2. template模板的复杂性

3、data数据的结构复杂性

4、网络情况

5、机型问题

6、最后


一、vue的生命周期 

1. 生命周期钩子函数

生命周期这个命名还是非常贴切的,他就像我们每个人,一出生如何如何,上学了该干什么,中年又有那些责任和义务,转眼,你的事情还没有做完,可能整个人就完犊子了。

init阶段

而vue组件的生命周期呢,包含了从最初的new Vue()开始,表示他要出生了,这里初始化一些id,name的属性,合并一些option参数(后边的vm.$options.el会用到),我们熟知的一些函数挂载上,以利于后续使用。可以说new Vue() 就是一个小孩出生的过程,把该有的器官,肢体,基本能力都预备上,虽然现在还不能用,发育还不成熟。

let uid = 0

Vue.prototype._init = function(options) {
  const vm = this
  vm._uid = uid++  // uid累加唯一标识
  
  vm.$options = mergeOptions(  // 合并options
    resolveConstructorOptions(vm.constructor),
    options || {},
    vm
  )
  ...
  initLifecycle(vm) // 初始化
  initEvents(vm)  // v-on识别处理
  initRender(vm) // render与vnode的结合
}

beforeCreate

正是有了前面的初始化,所以特意在这里为我们挂载了一个钩子函数,也就是这个生命周期。

其实你有没有发现,这个声明周期就像婴儿期的孩子,吃奶,哭,闹,啥也干不了。而我们在项目中基本也用不到。

callHook(vm, 'beforeCreate')

created

在beforeCreated到created这一阶段,数据依赖以形成,也就是我们常说的那个data函数,函数也可以调用,我们所写的template虚拟模板也逐渐被识别,但识别归识别,vnode还没转换成真正的DOM结构,所以data数据和模板中的v-model匹配不上。

initInjections(vm)
initState(vm)
initProvide(vm)
callHook(vm, 'created')

注意这一步的vnode和template还只是内存中的活动,生成的只是内存中的一个模板字符串,后续需要真正的将虚拟模板挂载到页面中去。

befoteMounted 

这一阶段承接created和mounted,data数据依赖有了,method方法有了,他需要不断的将内存中的虚拟模板字符串往DOM挂载,data数据是最新的,所以模板在根据虚拟模板的结构,根据data依赖的数据格式整合靠拢

mounted

这里基本就是孩子已经成熟了,数据依赖已有,methods已准备好,模板挂载为DOM,可以做DOM操作了。其实你发现,翻来覆去的说这么创新,那么实现,前端还是取DOM改DOM。这一点使得前端技术在很大一段时间,很长一段时间不会有多么惊人的不同。

beforeUpdate

现在动不动讲究数据驱动,当我们改变了data数据依赖,就开始beforeUpdate了,这个阶段更重要的是有一份真是DOM,有一份虚拟DOM,然后再根据新的data数据依赖,再生成一份虚拟DOM。紧接着就是我们时常有点懵的diff算法。经过一系列的胡乱操作之后,虚拟DOM更新完成,实现了data(Model数据)-----驱动----->view(视图)。

经常有人问:vue和react哪个更优秀?性能更高?其实这个结论没人下,一来一旦有权威的结论了,那么那么多人在使用着另一个技术栈,你让他怎么办?换技术栈?二来事实证明,不是人家底层技术栈做的好不好,而是你们团队一顿操作猛如虎,谁接手谁痛苦。

updated

这个阶段,最新的DOM已经更新出来,和data数据依赖的结构保持了一致。

这个时候蕴含着的一道题就是:vue出现了data已经更新,但视图没有更新的情况。

beforeDestroy

注意,这里是销毁前,用一个经典成语就是回光返照。虽然即将要销毁,但是data method 指令都还可用。但更应该注意的是真实DOM是否还存在的问题。

<template>
  <div id="demo">007</div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      num: 77
    }
  },
  mounted() {
    this.print7('method');
  },
  methods: {
    print7(type) {
      let demoDom = document.querySelector('#demo');
      console.log(`--${type}--`, demoDom);
      console.log(`--${type}--`, this.num);
    }
  },
  beforeDestroy() {
    this.print7('destroy');
  }
}
</script>

 

 

destroyed

这个组件的数据,方法,模板,过滤器都销毁了。

小结:

Vue的生命周期包含初始化(init)、创建前(beforeCreate)、创建后(created)、载入前(beforeMount)、载入后(mounted)、更新前(beforeUpdate)、更新后(updated)、销毁前(beforeDestroy)、销毁后(destroyed) 这9大生命周期。

 

 

2. 常用的几个钩子

created

这个生命周期很明显数据data已有,真实DOM未挂载,所以我们可以做大图片的预加载,可以提前发送ajax请求,但这个时候容易出现远程的ajax请求比本地js代码执行还快,还没到mounted呢,response数据已经回来了。而返回的数据无法与DOM做绑定。所以可以用到nextTick

created() {
    this.$nextTick(() => {
      fetch({
        url: 'http://xxx/user/list',
        param
      }).then((res) => {
        
      })
    })
  },

有一些页面的关键初始化接口请求会从这里发出去,我们可以在请求接口前打印一下时间戳,在请求到数据后打印一下时间戳,进行数据采集上报,这样再通过用户访问的数据积累,就可以大体衡量出我们这个关键接口,在大量数据的访问下,平均的时长如何,是否更优优化的空间,甚至很多时候可以做为前端向后端甩锅的一个强硬性的数据性的理由。

 

mounted 

这个阶段几乎只执行一次,但有一些监听浏览器行为的需要一直贯穿组件整个周期的事件可以放这里,例如监测浏览器滚动的事件:

mounted() {
   window.onscroll(() => {
      console.log('监听浏览器滚动');
   })
},

updated 

这个过程固然可以监听组件的数据变化,但往往我们又可以使用computed计算函数来更好的利用缓存特性来做一些数据的更新处理

destroyed

说实话,你的组件中如果没有制造一些全局变量,全局的定时器,这个生命周期可能一个月也用不到一次。

 

3. 为什么关掉组件,定时器还在执行?

之前所做的一切努力,都烟消云散了,数据,方法,模板,过滤器。但一个人从这个世上离开了,并不是真的离开,直到最后一个还记着他的人离开了,才算真的离开了。

我们知道app.js从一开始挂载到DOM上,我们不断往这个单页面应用上挂载组件,其实整个项目应用简直就是一个庞然大物,被无数个小Vue组件悬挂着,所以某个组件如果在运行中的时候,产生了全局的变量,定时器等,是不会随着destroyed的销毁而消失的。

就像这个大树神经网络一样,某个枝干虽然不在了,但是神经还能触达某个其他区域。

 

二、父子组件生命周期执行顺序

1. 嵌套一个子组件

首先是父组件,这里做了4步,布局组件模板、引入MyTitle组件、注册组件、传参

<template>
  <my-title 
    :title="title" />
</template>

<script>
import MyTitle from './MyTitle';
export default {
  name: 'HelloWorld',
  components: { MyTitle },
  data () {
    return {
      title: '这是一个标题组件',
    }
  },
  created() {
    console.log('父组件的created');
  },
  mounted() {
    console.log('父组件的mounted');
  },
}
</script>

然后是子组件的开发编写,主要是2步,通过props接收父组件参数,在子组件模板中渲染title参数

<template>
  <div class="t">{{ title }}</div>
</template>

<script>
export default {
  name: 'MyTitle',
  props: ['title'],
  data () {
    return {}
  },
  created() {
    console.log('子组件的created');
  },
  mounted() {
    console.log('子组件的mounted');
  }
}
</script>

显示结果:

 

 

2. 查看执行顺序

这也正好印证的组件的生命周期顺序,首先是父组件的created周期,这个时候的重要事情是处理虚拟DOM的过程,所以凡是父组件中挂载的子组件,都需要先识别,转换,处理,最后挂载为真实的DOM,才能继续执行父组件的mounted周期。 

三、created和mounted之间的时间差,影响因素有哪些?

如果这个问题,解说的再详细一点,就是其他不透露,已知created的钩子函数里只写了一行代码,打印了一个时间戳;mounted的钩子函数也只写了一行代码,打印了一个时间戳,那么他们的时间差值,影响因素会是哪些?

created() {
   console.log((new Date()).getTime());
},
mounted() {
  console.log((new Date()).getTime());
},

 

1.  beforeMounted

别的不说,这两个生命周期中间有个明显的beforeMounted周期卡着,如果在这个阶段做一件费事的事情,将是一个影响因素;

2. template模板的复杂性

如果简单做一个demo,template模板里我们只写几个单纯的div元素,和真实项目中做了N个组件,组件中又嵌套了几个elementui组件比,再结合我们第二点所说的父子组件生命周期的执行顺序可知,template的复杂性也将是一个影响时间差值的因素;

3、data数据的结构复杂性

mounted这个生命周期阶段呢,是真实DOM已挂载完成,之前所做的非常重要的一件事就是vnode与data数据层的结合,所以data数据如果结构复杂,map套了数组,数组里又套了map这些复合型数据结构,必将也是一个影响因素;

4、网络情况

真实项目中,我们可能会将vue.min.js抽离以减少主业务js的体积大小,而主业务js也可能走了其他服务线路,很可能中间还会有其他的执行文件,所以,某些大型的平台,用户网络千差万别,可能执行时间上也会有所不同吧;

5、机型问题

一旦引入了某个技术框架,很多人最爱比较的就是这个框架底层支持的代码体积是多少,为什么会有这个疑问呢,因为体积越多代码就越多啊,如果有人用着一部3年前的老人机,有人拿出了刚刚秒杀的旗舰机,执行速度肯定是不一样的。

我记得曾经问过一个人,他们的代码会在路边的某些公用设备上执行。你想一个不舍昼夜的机器,跑了3年了,和昨天新安装的机器比,是否会有所不同呢。

6、最后

如果你觉得某一点对你有帮助了,请告诉我,让我继续发扬自己的优势;如果你觉得我哪里写的不好呢,请告诉我,我继续学习;我是csdn经海路大白狗,希望和你共同学习前端知识,探讨未来的程序人员。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/167614.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

单链表

插入&#xff1a; head 表示头结点的下标 e[i] 表示节点i的值 ne[i] 表示节点i的next指针是多少 idx 存储当前已经用到了哪个点 步骤&#xff1a;1.初始化head 2.将x插到头结点 3.插入&#xff1a;将x插到下标是k的点后面 4.将x插到下标是k的点后面 5.将下标是k的点后面…

springboot,vue影院订票系统

开发工具&#xff1a;IDEA服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8项目构建&#xff1a;maven数据库&#xff1a;mysql5.7系统用户前台和管理后台两部分&#xff0c;项目采用前后端分离前端技术&#xff1a;vue elementUI服务端技术&#xff1a;springbootmybatis项目功…

集合框架及背后的数据结构

集合框架及背后的数据结构1. 介绍2. 学习的意义2.1 Java 集合框架的优点及作用2.2 笔试及面试题3. 接口 interfaces3.1 基本关系说明3.2 Collection 接口说明3.3 Collection 常用方法说明3.4 Collection 示例3.5 Map 接口说明Map3.6 Map 常用方法说明3.7 Map 示例4. 实现 class…

免费AI改图神器,一个万能宝藏在线工具箱

说到工具箱&#xff0c;无论是在线工具&#xff0c;还是软件应用都非常多。 比如想要抠一张图片&#xff0c;如果专业处理&#xff0c;那么会使用到 Photoshop&#xff0c;需要一定的学习成本&#xff0c;想要更快捷处理&#xff0c;那么会直接使用在线工具&#xff0c;网络上…

Secret

目录 文章目录目录本节实战前言1、Opaque Secret1.创建Secret&#xff08;1&#xff09;通过data字段来创建secret资源对象&#xff08;2&#xff09;通过stringData字段来创建secret资源对象&#xff08;3&#xff09;通过kubectl create命令来创建Opaque类型的Secret资源2.使…

ROS2 基础概念 参数

ROS2 基础概念 参数1. Parameters2. 参数3. 参数查看4. 参数设置5. 参数保存6. 参数加载1. Parameters 指令功能ros2 param delete /node parameter删除参数值ros2 param describe /node parameter显示参数的相关描述ros2 param dump /file将参数保存到一个文件中ros2 param g…

LinuxDeployQT打包QT程序

系统&#xff1a;ubuntu20.04官网可直接下载使用https://github.com/probonopd/linuxdeployqt/releases&#xff0c;但是因为不支持ubuntu20所以本文通过下载源码编译的方式编译linuxdeployqt安装编译相关依赖sudo apt-get install git g libgl1-mesa-dev wget安装QTsudo apt-g…

大数据之Kafka Shell命令和Java API

文章目录前言一、Kafka相关Shell命令&#xff08;一&#xff09;创建并查询Topic&#xff08;二&#xff09;删除Topic&#xff08;三&#xff09;增加Topic的分区&#xff08;四&#xff09;生产数据到Topic&#xff08;五&#xff09;从Topic消费数据总结前言 #博学谷IT学习…

机器学习笔记之深度玻尔兹曼机(一)玻尔兹曼机系列整体介绍

机器学习笔记之深度玻尔兹曼机——玻尔兹曼机系列整体介绍引言关于含隐变量模型的对数似然梯度玻尔兹曼机受限玻尔兹曼机深度信念网络深度玻尔兹曼机引言 从本节开始&#xff0c;将介绍玻尔兹曼机系列的最后一个模型——深度玻尔兹曼机(Deep Boltzmann Machine,DBM) 关于含隐…

【状态设计优化DP】P4310 绝世好题

不愧是绝世好题和abc那道E一样&#xff0c;也是重新定义状态来优化转移复杂度的DP(56条消息) Atcoder Beginner Contest E - Work or Rest_lamentropetion的博客-CSDN博客这种其实就是通过转移方式的特殊性来设计状态&#xff0c;从而降低复杂度其实我感觉降低复杂度优化就是因…

数据结构——括号匹配问题

这是一道常见的经典的数据结构中栈的问题。题目&#xff1a;20. 有效的括号 - 力扣&#xff08;LeetCode&#xff09;我们运用C语言实现这个问题。有效括号调用栈由于要涉及到栈的问题&#xff0c;不可避免的要运用栈的函数接口。比较直接的方法是&#xff0c;直接复制 栈 的代…

通过windows程序计划设定nginx开机自启动

通过windows程序计划设定nginx开机自启动1、按下win键输入计划&#xff0c;回车2、找到windows目录&#xff0c;在当下目录创建新任务3、自定义名称描述4、将触发设定为开机自启动5.点击下一步&#xff0c;程序或脚本选择nginx.exe所在目录&#xff0c;要把下面的起始于 处填上…

算法训练营 day20 二叉树 最大二叉树 合并二叉树 二叉搜索树中的搜索 验证二叉树

算法训练营 day20 二叉树 最大二叉树 合并二叉树 二叉搜索树中的搜索 验证二叉树 最大二叉树 654. 最大二叉树 - 力扣&#xff08;LeetCode&#xff09; 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值…

《Linux Shell脚本攻略》学习笔记-第十一章

11.1 简介 本章将会讲述如何获取相关网络分组。CPU占用率、磁盘使用情况以及东台调用的更多信息。 11.2 使用tcpdump跟踪分组 tcpdump需要以root身份运行。 关键字port可以只显示出发往或者来自特定端口的分组 src修饰符配合特定的“关键字-值”就可以指定源文件中的这类分组。…

Linux chown 命令

Linux chown&#xff08;英文全拼&#xff1a;change owner&#xff09;命令用于设置文件所有者和文件关联组的命令。Linux/Unix 是多人多工操作系统&#xff0c;所有的文件皆有拥有者。利用 chown 将指定文件的拥有者改为指定的用户或组&#xff0c;用户可以是用户名或者用户 …

基于机器学习 实现APT 检测(附完整代码)

项目环境概述以机器学习的方式&#xff0c;可以通过多种模型对 APT 组织所使用的恶意代码进行训练学习&#xff0c;同时由于训练的多样化&#xff0c;检测效果也会比家好。本项目采用的随机森林以及不同采样策略进行模型训练。详细设计见md文件。1.系统描述本系统主要是针对大量…

ElementUI中树形表格下拉卡死的问题解决

文章目录错误现象与描述&#xff1a;代码案例&#xff1a;错误现象与描述&#xff1a; 最近在修改一个前端的问题&#xff0c;发现后台返回给前端有数据&#xff0c;SQL查询也很快&#xff0c;但是就是前端的表格这里一直卡死&#xff0c;后来发现其他数据正常&#xff0c;其中…

【代码随想录】343. 整数拆分

343. 整数拆分 动态规划五部曲 1. 确定dp数组以及下标的含义 dp[i]&#xff1a;分拆数字i&#xff0c;可以得到的最大乘积为dp[i]。 2. 确定递推公式 其实可以从1遍历j&#xff0c;然后有两种渠道得到dp[i]. 一个是j * (i - j) 直接相乘。 一个是j * dp[i - j]&#xff0c;相…

文本向量化

1、one-hot 在one-hot里面每一个token用一个长度为N向量表示&#xff0c;N表示的是词典的数据量。&#xff08;不重复的词数量&#xff09; 缺点&#xff1a;维度太高&#xff0c;用稀疏向量表示文本。 2、word embedding 使用float的矩阵来表示token&#xff0c;根据词典的…

Qt环境生成dump文件解决程序异常崩溃以及生成日志文件

一、背景 1、在测试自己的项目代码过程 ① 程序的编译的时候没有报错&#xff0c;程序在Qt release模式下运行程序&#xff0c;程序运行五个小时后异常退出&#xff0c;The process was ended forcefully&#xff1b;② 以及在项目程序通过windeployqt 工具打包发布的程序&am…