文章目录
vue3声明周期图示
与vue2生命周期的两点区别:
- vue3先创建app实例挂载到el模块上才执行Create操作。
vue2是先create再将app实例挂载到el模块 - vue3组件生命周期的最后是卸载(unmount),与挂载mount对应;
而vue2组件生命周期的最后是销毁destory
vue3的声明周期流程演示
通过配置项的形式使用生命周期钩子
Vue3.0中可以继续使用Vue2.x中的生命周期钩子,但有有两个被更名:
- beforeDestroy改名为beforeUnmount
- destroyed改名为unmounted
Demo.vue
<template>
<h1>Demo组件</h1>
<h2>当前求和为:{{sum}}</h2>
<button @click="sum++">点我+1</button>
</template>
<script>
import {ref} from 'vue'
export default {
name: 'DemoVue',
setup() {
// 数据
let sum = ref(0)
return {
sum,
}
},
// 通过配置项的形式使用生命周期钩子
beforeCreate() {
console.log("---beforeCreate---")
},
created() {
console.log("---created---")
},
beforeMount(){
console.log("---beforeMount---")
},
mounted() {
console.log("---mounted---")
},
beforeUpdate(){
console.log("---beforeUpdate---")
},
updated() {
console.log("---updated---")
},
beforeUnmount() {
console.log("---beforeUnmount---")
},
unmounted() {
console.log("---unmounted---")
},
}
</script>
App.vue
<template>
<button @click="isShowDemo = !isShowDemo ">显示/隐藏</button>
<!-- 如果v-if的值为false直接将组件卸载掉 -->
<demo v-if="isShowDemo" />
</template>
<script>
import Demo from './components/Demo.vue'
import {ref} from 'vue'
export default {
name: 'AppVue',
components: { Demo },
setup() {
let isShowDemo = ref(true)
return {isShowDemo}
}
}
</script>
效果:
组合式API向setup中编写生命周期钩子
Vue3.0也提供了Composition API
形式的生命周期钩子,,组合式API的编写方式就是在setup()函数中编写对应的生命周期钩子,与Vue3.x中钩子对应关系如下:
- beforeCreate ===> setup() (`即setup()默认引入beforeCreate 和created无需手动编写`)
- created =======> setup()
- beforeMount===> onBeforeMount
- mounted =======> onMounted
- beforeUpdate ===> onBeforeUpdate
- updated =======> onUpdated
- beforeUnmount ==> onBeforeUnmount
- unmounted=====> onUnmounted
eg:
Demo.vue
<template>
<h1>Demo组件</h1>
<h2>当前求和为:{{sum}}</h2>
<button @click="sum++">点我+1</button>
</template>
<script>
import {ref,onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted} from 'vue'
export default {
name: 'DemoVue',
setup() {
console.log("---setup---")
// 数据
let sum = ref(0)
// 函数
onBeforeMount(()=>{
console.log("---onBeforeMount---")
})
onMounted(()=>{
console.log("---onMounted---")
})
onBeforeUpdate(()=>{
console.log("---onBeforeUpdate---")
})
onUpdated(()=>{
console.log("---onUpdated---")
})
onBeforeUnmount(()=>{
console.log("---onBeforeUnmount---")
})
onUnmounted(()=>{
console.log("---onUnmounted---")
})
return {
sum,
}
},
}
</script>
效果:
组合式API和配置项编写方法的优先级
组合式API编写方法比配置项编写方法的优先级高一些,但是一般只写一种即可
生命周期钩子调用时机
onBeforeMount()
注册一个钩子,在组件被挂载之前被调用。
当这个钩子被调用时,组件已经完成了数据的响应式状态的设置,但还没有创建 DOM 节点。
这个钩子在服务器端渲染期间不会被调用
类型:
function onBeforeMount(callback: () => void): void
onMounted()
在组件挂载完成后执行。
已挂载的判断条件:
- 其所有同步子组件都已经被挂载 (不包含异步组件或
<Suspense>
树内的组件)。 - 其自身的
DOM 树已经创建完成并插入了父容器
中。
这个钩子在服务器端渲染期间不会被调用。
类型:
function onMounted(callback: () => void): void
onBeforeUpdate
在组件即将因为响应式状态变更而更新其 DOM 树之前调用。
- 在这个组件中更改组件状态是安全的。
这个钩子在服务器端渲染期间不会被调用。
类型:
function onBeforeUpdate(callback: () => void): void
onUpdated
在组件因为响应式状态变更而更新其 DOM 树之后
调用。
- 父组件的更新钩子将在其子组件的更新钩子之后调用。
- 这个钩子会在组件的任意 DOM 更新后被调用,这些更新可能是由
不同的状态变更
导致的,因为多个状态变更可以在同一个渲染周期中批量执行。如果你需要在某个特定的状态
更改后访问更新后的 DOM,请使用 nextTick() 作为替代。 - 不要在 updated 钩子中更改组件的状态,这可能会导致无限的更新循环!
这个钩子在服务器端渲染期间不会被调用。
类型:
function onUpdated(callback: () => void): void
onBeforeUnmount
在组件实例被卸载之前调用。
- 当这个钩子被调用时,组件实例依然还保有全部的功能。
这个钩子在服务器端渲染期间不会被调用。
类型
function onBeforeUnmount(callback: () => void): void
onUnmounted
在组件实例被卸载之后调用。
组件实例卸载的判断条件:
- 其所有子组件都已经被卸载。
- 所有相关的响应式作用 (渲染作用以及 setup() 时创建的计算属性和侦听器) 都已经停止。
这个钩子在服务器端渲染期间不会被调用。
类型
function onUnmounted(callback: () => void): void
注意事项
- onMounted 的调用时机
当调用 onMounted 时,Vue 会自动将回调函数注册到当前正被初始化的组件实例上
。
这意味着这些钩子应当在组件初始化时被同步注册。例如,请不要这样做:
setTimeout(() => {
onMounted(() => {
// 异步注册时当前组件实例已丢失
// 这将不会正常工作
})
}, 100)
注意这并不意味着对 onMounted 的调用必须放在 setup()
或 <script setup>
内的词法上下文中。onMounted() 也可以在一个外部函数中调用,只要调用栈是同步的,且最终起源自 setup() 就可以。
其他的一些生命周期钩子
onErrorCaptured
在捕获后代组件传递的错误时调用。
- 类型:
function onErrorCaptured(callback: ErrorCapturedHook): void
type ErrorCapturedHook = (
err: unknown,
instance: ComponentPublicInstance | null,
info: string
) => boolean | void
回调函数有三个参数:错误对象、触发错误的组件实例、说明错误来源类型信息的字符串。
-
可捕获的错误类型:
组件渲染错误、事件处理错误、生命周期钩子错误、setup()函数错误
、监听器watch错误、自定义指令错误、过渡钩子错误。 -
使用:
一般在钩子中更改组件状态来为用户显示一个错误状态。 -
错误的传递规则:
- 所有的错误都会被发送到应用级的
app.config.errorHandler
(前提是这个函数已经定义),这样这些错误都能在一个统一的地方报告给分析服务。 - 如果组件的继承链或组件链上存在
多个 errorCaptured
钩子,对于同一个错误,这些钩子会被按从底至上的顺序一一调用。这个过程被称为“向上传递” - errorCaptured 钩子可以通过返回 false 来阻止错误继续向上传递。即表示“这个错误已经被处理了,应当被忽略”。
- 所有的错误都会被发送到应用级的
onRenderTracked
当组件渲染过程中追踪到响应式依赖
时调用。
这个钩子仅在开发模式
下可用,且在服务器端渲染期间不会被调用。
类型:
function onRenderTracked(callback: DebuggerHook): void
type DebuggerHook = (e: DebuggerEvent) => void
type DebuggerEvent = {
effect: ReactiveEffect
target: object
type: TrackOpTypes /* 'get' | 'has' | 'iterate' */
key: any
}
onRenderTriggered
当响应式依赖的变更触发组件渲染的时候调用。
这个钩子仅在开发模式下可用,且在服务器端渲染期间不会被调用。
类型:
function onRenderTriggered(callback: DebuggerHook): void
type DebuggerHook = (e: DebuggerEvent) => void
type DebuggerEvent = {
effect: ReactiveEffect
target: object
type: TriggerOpTypes /* 'set' | 'add' | 'delete' | 'clear' */
key: any
newValue?: any
oldValue?: any
oldTarget?: Map<any, any> | Set<any>
}
onActivated
注册一个回调函数,若组件实例是 <KeepAlive>
缓存树的一部分,当组件被插入到 DOM
中时调用。
这个钩子在服务器端渲染期间不会被调用。
类型
function onActivated(callback: () => void): void
onDeactivated
注册一个回调函数,若组件实例是 <KeepAlive>
缓存树的一部分,当组件从 DOM 中被移除
时调用。
这个钩子在服务器端渲染期间不会被调用。
类型
function onDeactivated(callback: () => void): void
onServerPrefetch
注册一个异步函数
,在组件实例在服务器上被渲染之前调用。
- 如果这个钩子返回了一个 Promise,服务端渲染会在渲染该组件前等待该 Promise 完成。
- 这个钩子
仅会在服务端渲染中执行
,可以用于执行一些仅存在于服务端的数据抓取过程。
类型
function onServerPrefetch(callback: () => Promise<any>): void
示例:
<script setup>
import { ref, onServerPrefetch, onMounted } from 'vue'
const data = ref(null)
onServerPrefetch(async () => {
// 组件作为初始请求的一部分被渲染
// 在服务器上预抓取数据,因为它比在客户端上更快。
data.value = await fetchOnServer(/* ... */)
})
onMounted(async () => {
if (!data.value) {
// 如果数据在挂载时为空值,这意味着该组件 是在客户端动态渲染的。
// 将转而执行另一个客户端侧的抓取请求
data.value = await fetchOnClient(/* ... */)
}
})
</script>