Vue 3 生命周期完整指南(vue生命周期及使用)
ztj100 2025-04-30 21:22 57 浏览 0 评论
Vue2 和 Vue3 中的生命周期钩子的工作方式非常相似,我们仍然可以访问相同的钩子,也希望将它们能用于相同的场景。
如果项目使用 选项 API,就不必更改任何代码了,因为 Vue3 兼容以前的版本。
当然,我们用 Vue3 就是要用它的 组合 API,组合 API中访问这些钩子的方式略有不同,组合API在较大的Vue项目中特别有用。
本文主要内容:
- Vue生命周期钩子有哪些
- 在选项API中使用 Vue 生命周期钩子
- 在组合API中使用Vue 3生命周期钩子
- 将 Vue2 的生命周期钩子代码更新到 Vue3
- 看看Vue 2和Vue 3中的每个生命周期钩子
- 创建
- 挂载
- 更新
- 卸载
- 激活
- Vue 3中的新调试钩子
Vue生命周期钩子有哪些
首先,来看一下 选项API 和 组合 API中 Vue 3生命周期钩子的图表。在深入细节之前,这能加深我们的理解。
本质上,每个主要Vue生命周期事件被分成两个钩子,分别在事件之前和之后调用。Vue应用程序中有4个主要事件(8个主要钩子)。
- 创建 — 在组件创建时执行
- 挂载 — DOM 被挂载时执行
- 更新 — 当响应数据被修改时执行
- 销毁 — 在元素被销毁之前立即运行
在选项API中使用 Vue 生命周期钩子
使用 选项API,生命周期钩子是被暴露 Vue实例上的选项。我们不需要导入任何东西,只需要调用这个方法并为这个生命周期钩子编写代码。
例如,假设我们想访问mounted()和updated()生命周期钩子,可以这么写:
// 选项 API
<script>
export default {
mounted() {
console.log('mounted!')
},
updated() {
console.log('updated!')
}
}
</script>
在组合API中使用Vue 3生命周期钩子
在组合API中,我们需要将生命周期钩子导入到项目中,才能使用,这有助于保持项目的轻量性。
// 组合 API
import { onMounted } from 'vue'
除了beforecate和created(它们被setup方法本身所取代),我们可以在setup方法中访问的API生命周期钩子有9个选项:
- onBeforeMount – 在挂载开始之前被调用:相关的 render 函数首次被调用。
- onMounted – 组件挂载时调用
- onBeforeUpdate – 数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
- onUpdated – 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
- onBeforeUnmount – 在卸载组件实例之前调用。在这个阶段,实例仍然是完全正常的。
- onUnmounted – 卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。
- onActivated – 被 keep-alive 缓存的组件激活时调用。
- onDeactivated – 被 keep-alive 缓存的组件停用时调用。
- onErrorCaptured – 当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。
使用事例:
// 组合 API
<script>
import { onMounted } from 'vue'
export default {
setup () {
onMounted(() => {
console.log('mounted in the composition api!')
})
}
}
</script>
将 Vue2 的生命周期钩子代码更新到 Vue3
这个从Vue2 到Vue3的生命周期映射是直接从Vue 3 Composition API文档中获得的:
- beforeCreate -> 使用 setup()
- created -> 使用 setup()
- beforeMount -> onBeforeMount
- mounted -> onMounted
- beforeUpdate -> onBeforeUpdate
- updated -> onUpdated
- beforeDestroy -> onBeforeUnmount
- destroyed -> onUnmounted
- errorCaptured -> onErrorCaptured
深入了解每个生命周期钩子
我们现在了解了两件重要的事情:
- 我们可以使用的不同的生命周期钩子
- 如何在选项API和组合API中使用它们
我们深入一下每个生命周期钩子,看看它们是如何被使用的,我们可以在每个钩子中编写特定代码,来测试在Options API和Composition API中的各自的区别。
beforeCreate() – 选项 API
由于创建的挂钩是用于初始化所有响应数据和事件的事物,因此beforeCreate无法访问组件的任何响应数据和事件。
以下面的代码块为例:
// 选项 API
export default {
data() {
return {
val: 'hello'
}
},
beforeCreate() {
console.log('Value of val is: ' + this.val)
}
}
val的输出值是 undefined,因为尚未初始化数据,我们也不能在这调用组件方法。
如果你想查看可用内容的完整列表,建议只运行console.log(this)来查看已初始化的内容。当使用选项API时,这做法在其他钩子中也很有用。
created() – 选项 API
如果我们要在组件创建时访问组件的数据和事件,可以把上面的 beforeCreate 用 created代替。
// 选项API
export default {
data() {
return {
val: 'hello'
}
},
created() {
console.log('Value of val is: ' + this.val)
}
}
其输出为Value of val is: hello,因为我们已经初始化了数据。
在处理读/写反应数据时,使用created 的方法很有用。例如,要进行API调用然后存储该值,则可以在此处进行此操作。
最好在这里执行此操作,而不是在mounted 中执行此操作,因为它发生在Vue的同步初始化过程中,并且我们需要执行所有数据读取/写入操作。
那么组合API的创建钩子呢?
对于使用 组合API 的 Vue3 生命周期钩子,使用setup()方法替换beforecate和created。这意味着,在这些方法中放入的任何代码现在都只在setup方法中。
// 组合AP
import { ref } from 'vue'
export default {
setup() {
const val = ref('hello')
console.log('Value of val is: ' + val.value)
return {
val
}
}
}
beforeMount() and onBeforeMount()
在组件DOM实际渲染安装之前调用。在这一步中,根元素还不存在。在选项API中,可以使用this.$els来访问。在组合API中,为了做到这一点,必须在根元素上使用ref。
// 选项 API
export default {
beforeMount() {
console.log(this.$el)
}
}
组合API中使用 ref:
// 组合 API
<template>
<div ref='root'>
Hello World
</div>
</template>
import { ref, onBeforeMount } from 'vue'
export default {
setup() {
const root = ref(null)
onBeforeMount(() => {
console.log(root.value)
})
return {
root
}
},
beforeMount() {
console.log(this.$el)
}
}
因为app.$el还没有创建,所以输出将是undefined。
mounted() and onMounted()
在组件的第一次渲染后调用,该元素现在可用,允许直接DOM访问
同样,在 选项API中,我们可以使用this.$el来访问我们的DOM,在组合API中,我们需要使用refs来访问Vue生命周期钩子中的DOM。
import { ref, onMounted } from 'vue'
export default {
setup() { /* 组合 API */
const root = ref(null)
onMounted(() => {
console.log(root.value)
})
return {
root
}
},
mounted() { /* 选项 API */
console.log(this.$el)
}
}
beforeUpdate() and onBeforeUpdate()
数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
beforeUpdate对于跟踪对组件的编辑次数,甚至跟踪创建“撤消”功能的操作很有用。
updated() and onUpdated()
DOM更新后,updated的方法即会调用。
<template>
<div>
<p>{{val}} | edited {{ count }} times</p>
<button @click='val = Math.random(0, 100)'>Click to Change</button>
</div>
</template>
选项 API 方式:
export default {
data() {
return {
val: 0
}
},
beforeUpdate() {
console.log("beforeUpdate() val: " + this.val)
},
updated() {
console.log("updated() val: " + this.val
}
}
组合API的方式:
import { ref, onBeforeUpdate, onUpdated } from 'vue'
export default {
setup () {
const count = ref(0)
const val = ref(0)
onBeforeUpdate(() => {
count.value++;
console.log("beforeUpdate");
})
onUpdated(() => {
console.log("updated() val: " + val.value)
})
return {
count, val
}
}
}
这些方法很有用,但是对于更多场景,我们需要使用的watch方法检测这些数据更改。watch 之所以好用,是因为它给出了更改后的数据的旧值和新值。
另一种选择是使用计算属性来基于元素更改状态。
beforeUnmount() 和 onBeforeUnmounted()
在卸载组件实例之前调用。在这个阶段,实例仍然是完全正常的。
在 选项 API中,删除事件侦听器的示例如下所示。
// 选项 API
export default {
mounted() {
console.log('mount')
window.addEventListener('resize', this.someMethod);
},
beforeUnmount() {
console.log('unmount')
window.removeEventListener('resize', this.someMethod);
},
methods: {
someMethod() {
// do smth
}
}
}
// 组合API
import { onMounted, onBeforeUnmount } from 'vue'
export default {
setup () {
const someMethod = () => {
// do smth
}
onMounted(() => {
console.log('mount')
window.addEventListener('resize', someMethod);
})
onBeforeUnmount(() => {
console.log('unmount')
window.removeEventListener('resize', someMethod);
})
}
}
实际操作的一种方法是在Vite,vue-cli或任何支持热重载的开发环境中,更新代码时,某些组件将自行卸载并安装。
unmounted() 和 onUnmounted()
卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。
import { onUnmounted } from 'vue'
export default {
setup () { /* 组合 API */
onUnmounted(() => {
console.log('unmounted')
})
},
unmounted() { /* 选项 API */
console.log('unmounted')
}
}
activated() and onActivated()
被keep-alive 缓存的组件激活时调用。
例如,如果我们使用keep-alive组件来管理不同的选项卡视图,每次在选项卡之间切换时,当前选项卡将运行这个 activated 钩子。
假设我们使用keep-alive包装器进行以下动态组件。
<template>
<div>
<span @click='tabName = "Tab1"'>Tab 1 </span>
<span @click='tabName = "Tab2"'>Tab 2</span>
<keep-alive>
<component :is='tabName' class='tab-area'/>
</keep-alive>
</div>
</template>
<script>
import Tab1 from './Tab1.vue'
import Tab2 from './Tab2.vue'
import { ref } from 'vue'
export default {
components: {
Tab1,
Tab2
},
setup () { /* 组合 API */
const tabName = ref('Tab1')
return {
tabName
}
}
}
</script>
在Tab1.vue组件内部,我们可以像这样访问activated钩子。
<template>
<div>
<h2>Tab 1</h2>
<input type='text' placeholder='this content will persist!'/>
</div>
</template>
<script>
import { onActivated } from 'vue'
export default {
setup() {
onActivated(() => {
console.log('Tab 1 Activated')
})
}
}
</script>
deactivated() 和 onDeactivated()
被 keep-alive 缓存的组件停用时调用。
这个钩子在一些用例中很有用,比如当一个特定视图失去焦点时保存用户数据和触发动画。
import { onActivated, onDeactivated } from 'vue'
export default {
setup() {
onActivated(() => {
console.log('Tab 1 Activated')
})
onDeactivated(() => {
console.log('Tab 1 Deactivated')
})
}
}
现在,当我们在选项卡之间切换时,每个动态组件的状态都将被缓存和保存。
Vue3 调试钩子
Vue3 为我们提供了两个可用于调试目的的钩子。
- onRenderTracked
- onRenderTriggered
这两个事件都带有一个debugger event,此事件告诉你哪个操作跟踪了组件以及该操作的目标对象和键。
onRenderTracked
跟踪虚拟 DOM 重新渲染时调用。钩子接收 debugger event 作为参数。此事件告诉你哪个操作跟踪了组件以及该操作的目标对象和键。
<div id="app">
<button v-on:click="addToCart">Add to cart</button>
<p>Cart({{ cart }})</p>
</div>
const app = Vue.createApp({
data() {
return {
cart: 0
}
},
renderTracked({ key, target, type }) {
console.log({ key, target, type })
/* 当组件第一次渲染时,这将被记录下来:
{
key: "cart",
target: {
cart: 0
},
type: "get"
}
*/
},
methods: {
addToCart() {
this.cart += 1
}
}
})
app.mount('#app')
renderTracked
当虚拟 DOM 重新渲染为 triggered.Similarly 为renderTracked,接收 debugger event作为参数。此事件告诉你是什么操作触发了重新渲染,以及该操作的目标对象和键。
用法:
<div id="app">
<button v-on:click="addToCart">Add to cart</button>
<p>Cart({{ cart }})</p>
</div>
const app = Vue.createApp({
data() {
return {
cart: 0
}
},
renderTriggered({ key, target, type }) {
console.log({ key, target, type })
},
methods: {
addToCart() {
this.cart += 1
/* 这将导致renderTriggered调用
{
key: "cart",
target: {
cart: 1
},
type: "set"
}
*/
}
}
})
app.mount('#app')
总结
无论你选择使用选项API还是 组合API,不仅要知道要使用哪个生命周期挂钩,而且要知道为什么要使用它,这一点很重要。
对于许多问题,可以使用多个生命周期钩子。但是最好知道哪个是最适合你用例的。无论如何,你都应该好好考虑一下,并有充分的理由去选择一个特定的生命周期钩子。
我希望这能帮助大家更多地理解生命周期钩子以及如何在大家的项目中实现它们。
~完,我是刷碗智,我要去刷碗了,骨的白。
作者:Michael Thiessen 译者:前端小智 来源:news
原文:https://learnvue.co/2020/12/how-to-use-lifecycle-hooks-in-vue3/
相关推荐
- 其实TensorFlow真的很水无非就这30篇熬夜练
-
好的!以下是TensorFlow需要掌握的核心内容,用列表形式呈现,简洁清晰(含表情符号,<300字):1.基础概念与环境TensorFlow架构(计算图、会话->EagerE...
- 交叉验证和超参数调整:如何优化你的机器学习模型
-
准确预测Fitbit的睡眠得分在本文的前两部分中,我获取了Fitbit的睡眠数据并对其进行预处理,将这些数据分为训练集、验证集和测试集,除此之外,我还训练了三种不同的机器学习模型并比较了它们的性能。在...
- 机器学习交叉验证全指南:原理、类型与实战技巧
-
机器学习模型常常需要大量数据,但它们如何与实时新数据协同工作也同样关键。交叉验证是一种通过将数据集分成若干部分、在部分数据上训练模型、在其余数据上测试模型的方法,用来检验模型的表现。这有助于发现过拟合...
- 深度学习中的类别激活热图可视化
-
作者:ValentinaAlto编译:ronghuaiyang导读使用Keras实现图像分类中的激活热图的可视化,帮助更有针对性...
- 超强,必会的机器学习评估指标
-
大侠幸会,在下全网同名[算法金]0基础转AI上岸,多个算法赛Top[日更万日,让更多人享受智能乐趣]构建机器学习模型的关键步骤是检查其性能,这是通过使用验证指标来完成的。选择正确的验证指...
- 机器学习入门教程-第六课:监督学习与非监督学习
-
1.回顾与引入上节课我们谈到了机器学习的一些实战技巧,比如如何处理数据、选择模型以及调整参数。今天,我们将更深入地探讨机器学习的两大类:监督学习和非监督学习。2.监督学习监督学习就像是有老师的教学...
- Python 模型部署不用愁!容器化实战,5 分钟搞定环境配置
-
你是不是也遇到过这种糟心事:花了好几天训练出的Python模型,在自己电脑上跑得顺顺当当,一放到服务器就各种报错。要么是Python版本不对,要么是依赖库冲突,折腾半天还是用不了。别再喊“我...
- 神经网络与传统统计方法的简单对比
-
传统的统计方法如...
- 自回归滞后模型进行多变量时间序列预测
-
下图显示了关于不同类型葡萄酒销量的月度多元时间序列。每种葡萄酒类型都是时间序列中的一个变量。假设要预测其中一个变量。比如,sparklingwine。如何建立一个模型来进行预测呢?一种常见的方...
- 苹果AI策略:慢哲学——科技行业的“长期主义”试金石
-
苹果AI策略的深度原创分析,结合技术伦理、商业逻辑与行业博弈,揭示其“慢哲学”背后的战略智慧:一、反常之举:AI狂潮中的“逆行者”当科技巨头深陷AI军备竞赛,苹果的克制显得格格不入:功能延期:App...
- 时间序列预测全攻略,6大模型代码实操
-
如果你对数据分析感兴趣,希望学习更多的方法论,希望听听经验分享,欢迎移步宝藏公众号...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- idea eval reset (50)
- vue dispatch (70)
- update canceled (42)
- order by asc (53)
- spring gateway (67)
- 简单代码编程 贪吃蛇 (40)
- transforms.resize (33)
- redisson trylock (35)
- 卸载node (35)
- np.reshape (33)
- torch.arange (34)
- npm 源 (35)
- vue3 deep (35)
- win10 ssh (35)
- vue foreach (34)
- idea设置编码为utf8 (35)
- vue 数组添加元素 (34)
- std find (34)
- tablefield注解用途 (35)
- python str转json (34)
- java websocket客户端 (34)
- tensor.view (34)
- java jackson (34)
- vmware17pro最新密钥 (34)
- mysql单表最大数据量 (35)