在 Vue 中,父组件和子组件的生命周期是相互独立的,但它们之间存在着某些交互。父组件和子组件在创建、更新、销毁等生命周期的不同阶段可能会相互影响。
父组件和子组件的生命周期钩子
1. 父组件生命周期
父组件的生命周期钩子与子组件相似,但父组件的生命周期会受到子组件的影响。在父组件中,子组件的创建、更新和销毁会触发相应的钩子。
beforeCreate
:在父组件创建前触发,但此时子组件尚未被创建。created
:父组件实例已创建,数据和事件已初始化,但尚未挂载到 DOM,此时子组件的实例还未创建。beforeMount
:父组件挂载前触发,子组件的实例已经创建,但还未挂载到 DOM。mounted
:父组件挂载后触发,子组件的 DOM 元素也已挂载。beforeUpdate
:当父组件的响应式数据发生变化并即将更新时触发,但此时子组件的 DOM 尚未更新。updated
:当父组件的数据更新并且视图重新渲染后触发,此时子组件的 DOM 已经更新。beforeUnmount
:当父组件将要销毁时触发,此时子组件也将销毁。unmounted
:当父组件销毁后触发,子组件的销毁也已完成。
2. 子组件生命周期
子组件的生命周期钩子与父组件的类似。子组件的创建和销毁是父组件生命周期的一部分,父组件和子组件的生命周期会有交集:
beforeCreate
:子组件实例创建前触发,父组件的beforeCreate
钩子已经执行,但子组件的data
、computed
、methods
尚未初始化。created
:子组件实例创建后触发,此时可以访问data
和props
,但尚未挂载到 DOM。此时可以获取初始数据或执行初始化任务。beforeMount
:子组件挂载前触发,父组件的beforeMount
钩子已经执行。mounted
:子组件挂载后触发,父组件的mounted
钩子也已触发。beforeUpdate
:子组件在数据发生变化,视图即将更新时触发。updated
:子组件在视图更新后触发,父组件的updated
钩子也已触发。beforeUnmount
:子组件将要销毁时触发,父组件的beforeUnmount
钩子也会被调用。unmounted
:子组件销毁后触发,父组件的unmounted
钩子也会被调用。
父子组件的生命周期交互
1. 父组件传递数据给子组件
父组件通过 props
向子组件传递数据。当父组件的状态发生变化时(例如通过 data
、computed
更新),子组件会重新渲染。这会触发子组件的更新生命周期钩子,如 beforeUpdate
和 updated
。
2. 子组件向父组件传递数据
子组件可以通过 $emit
向父组件发送事件,父组件通过监听这些事件来更新自身状态。父组件的状态变化也会影响子组件的渲染。
3. 销毁顺序
当父组件销毁时,子组件会先销毁。父组件的 beforeUnmount
和 unmounted
钩子会在子组件销毁后执行。这是因为 Vue 会先销毁子组件的实例,然后再销毁父组件。
生命周期执行顺序(父子组件)
以下是父子组件生命周期的执行顺序,假设父组件创建了一个子组件:
-
父组件:
beforeCreate
created
beforeMount
- 子组件:
beforeCreate
created
beforeMount
mounted
mounted
-
数据更新(父组件数据变化):
- 父组件:
beforeUpdate
updated
- 子组件:
beforeUpdate
updated
- 父组件:
-
销毁:
- 父组件:
beforeUnmount
- 子组件:
beforeUnmount
unmounted
- 父组件:
unmounted
- 父组件:
示例代码
父组件 (ParentComponent.vue)
vue复制代码<template>
<div>
<h1>父组件</h1>
<child-component :message="message" @updateMessage="updateMessage" />
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
import ChildComponent from './ChildComponent.vue'
const message = ref('Hello from Parent')
const updateMessage = (newMessage) => {
message.value = newMessage
}
onMounted(() => {
console.log('父组件已挂载')
})
onBeforeUnmount(() => {
console.log('父组件即将销毁')
})
</script>
子组件 (ChildComponent.vue)
vue复制代码<template>
<div>
<p>{{ message }}</p>
<button @click="sendMessage">Update Message</button>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount, defineProps, defineEmits } from 'vue'
const props = defineProps({
message: String
})
const emit = defineEmits(['updateMessage'])
const sendMessage = () => {
emit('updateMessage', 'New message from Child')
}
onMounted(() => {
console.log('子组件已挂载')
})
onBeforeUnmount(() => {
console.log('子组件即将销毁')
})
</script>
总结
- 父组件生命周期:在父组件创建、更新、销毁时,会触发与子组件交互的生命周期钩子。
- 子组件生命周期:子组件生命周期钩子受父组件生命周期的影响,并且子组件也有自己独立的生命周期。
- 交互与依赖:父组件和子组件之间可以通过
props
和$emit
实现数据和事件的交互,生命周期钩子可以帮助我们在不同阶段管理这些交互。