Vue生命周期,总也学不会,所以我详细整理了一下
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
今天我和大家一起来对vue生命周期做一个整理和思考希望有缘人看到我的年度整理和思考如果觉得靠谱呢就交个朋友如果觉得我整理的不足就请指出让我们一起进步让我们2023年能共同思考。
☆ 文本将进行3个小模块第一呢是老生常谈然后再结合我的理解说一说vue的生命周期有哪些每个阶段做了一些什么事情 而项目中我们可以做一些什么事情
☆ 第二呢说一下嵌套父子组件情况下生命周期的执行顺序
☆ 第三整理后思考一下created和mounted两个钩子之间的时间差可能会受哪些因素的影响
目录
三、created和mounted之间的时间差影响因素有哪些
一、vue的生命周期
1. 生命周期钩子函数
生命周期这个命名还是非常贴切的他就像我们每个人一出生如何如何上学了该干什么中年又有那些责任和义务转眼你的事情还没有做完可能整个人就完犊子了。
△ init阶段
而vue组件的生命周期呢包含了从最初的new Vue()开始表示他要出生了这里初始化一些idname的属性合并一些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和mounteddata数据依赖有了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模板的复杂性
如果简单做一个demotemplate模板里我们只写几个单纯的div元素和真实项目中做了N个组件组件中又嵌套了几个elementui组件比再结合我们第二点所说的父子组件生命周期的执行顺序可知template的复杂性也将是一个影响时间差值的因素
3、data数据的结构复杂性
mounted这个生命周期阶段呢是真实DOM已挂载完成之前所做的非常重要的一件事就是vnode与data数据层的结合所以data数据如果结构复杂map套了数组数组里又套了map这些复合型数据结构必将也是一个影响因素
4、网络情况
真实项目中我们可能会将vue.min.js抽离以减少主业务js的体积大小而主业务js也可能走了其他服务线路很可能中间还会有其他的执行文件所以某些大型的平台用户网络千差万别可能执行时间上也会有所不同吧
5、机型问题
一旦引入了某个技术框架很多人最爱比较的就是这个框架底层支持的代码体积是多少为什么会有这个疑问呢因为体积越多代码就越多啊如果有人用着一部3年前的老人机有人拿出了刚刚秒杀的旗舰机执行速度肯定是不一样的。
我记得曾经问过一个人他们的代码会在路边的某些公用设备上执行。你想一个不舍昼夜的机器跑了3年了和昨天新安装的机器比是否会有所不同呢。
6、最后
如果你觉得某一点对你有帮助了请告诉我让我继续发扬自己的优势如果你觉得我哪里写的不好呢请告诉我我继续学习我是csdn经海路大白狗希望和你共同学习前端知识探讨未来的程序人员。