父组件怎样监听子组件的生命周期?
先理解原理和示例,再练习完整口述与追问。
回答要点
最清晰的是子组件主动 emit 事件;Vue2 可用 @hook:mounted 监听任意子组件的生命周期钩子;Vue3 改为 @vue:mounted 这类 vnode 生命周期事件。需要拿到实例时用 ref 配合父组件 onMounted,父组件的 mounted 在子组件之后触发。
原理拆解
Vue2 组件在调用每个生命周期钩子时,会额外 $emit('hook:mounted'),所以父组件可以写 <Child @hook:mounted="onChildMounted" />,组件内部也能用 this.$once('hook:beforeDestroy', cleanup) 就近注册清理逻辑。Vue3 移除了 $on、$once,hook: 前缀写法也已废弃,改为 vnode 钩子 @vue:mounted、@vue:updated、@vue:before-unmount,这些写法官方文档中较少强调,团队内应统一说明。
挂载顺序是父 beforeMount → 子 beforeMount → 子 mounted → 父 mounted,所以父组件 onMounted 中子组件的 ref 已经可用;异步组件、v-if 晚出现的子组件则需要额外监听。
示例与推演
<script setup>
import { ref, onMounted } from 'vue'
const chart = ref(null)
const onChildReady = () => console.log('子组件已挂载')
onMounted(() => chart.value?.resize())
</script>
<template>
<ChartPanel ref="chart" @vue:mounted="onChildReady" />
</template>
易错点
用 vnode 钩子把父组件逻辑绑在子组件内部时机上,维护者不容易发现;子组件如果有异步数据,mounted 并不代表“数据准备好”,应由子组件 emit 业务事件(如 ready)。
参考回答可直接练习口述
最推荐的是子组件在合适时机 emit 一个业务事件,比如 ready。只是想知道挂载时机的话,Vue2 可以用 @hook:mounted,Vue3 改成 @vue:mounted 这类 vnode 生命周期事件。需要调用子组件方法时,用 ref 在父组件 onMounted 里访问,因为子组件先挂载完父组件才 mounted。如果子组件有异步数据,mounted 不代表数据就绪,还是要靠业务事件。