Vue3中如何等待异步组件挂载完成?
问题解决:异步组件挂载后获取实例的正确方式
你的代码场景中,HelloWorld是异步组件,直接用nextTick拿不到组件实例的原因是:nextTick仅等待当前DOM更新循环结束,但异步组件的代码加载、实例化和挂载需要额外时间,此时组件还未完成挂载,所以comp.value为null。下面提供几种不需要setTimeout的解决方案:
方案一:利用异步组件的onLoaded回调
直接在defineAsyncComponent的配置中指定组件加载完成后的回调,此时组件已经完成挂载,可以直接访问ref:
<template> <HelloWorld v-if="isShow" ref="comp"></HelloWorld> <button @click="show">Show</button> </template> <script> import { defineAsyncComponent, ref } from 'vue' export default { components: { HelloWorld: defineAsyncComponent({ loader: () => import('./HelloWorld.vue'), onLoaded: () => { console.log(comp.value) // 组件已挂载,可正常访问实例 } }) }, setup() { const isShow = ref(false) const comp = ref(null) const show = () => { isShow.value = true } return { isShow, comp, show } } } </script>
方案二:监听ref的变化
组件挂载完成后,comp的ref值会从null变为组件实例,通过watch监听这个变化即可:
<template> <HelloWorld v-if="isShow" ref="comp"></HelloWorld> <button @click="show">Show</button> </template> <script> import { defineAsyncComponent, ref, watch } from 'vue' export default { components: { HelloWorld: defineAsyncComponent(() => import('./HelloWorld.vue')) }, setup() { const isShow = ref(false) const comp = ref(null) watch(comp, (newInstance) => { if (newInstance) { console.log(newInstance) // 组件已挂载,拿到实例 } }) const show = () => { isShow.value = true } return { isShow, comp, show } } } </script>
方案三:组件内部主动通知挂载完成
在HelloWorld组件的onMounted钩子中emit事件,父组件监听该事件后访问ref:
HelloWorld.vue
<script> import { onMounted } from 'vue' export default { emits: ['component-mounted'], setup(props, { emit }) { onMounted(() => { emit('component-mounted') }) // 其他组件逻辑 } } </script>
父组件
<template> <HelloWorld v-if="isShow" ref="comp" @component-mounted="handleMounted" ></HelloWorld> <button @click="show">Show</button> </template> <script> import { defineAsyncComponent, ref } from 'vue' export default { components: { HelloWorld: defineAsyncComponent(() => import('./HelloWorld.vue')) }, setup() { const isShow = ref(false) const comp = ref(null) const handleMounted = () => { console.log(comp.value) // 组件已挂载 } const show = () => { isShow.value = true } return { isShow, comp, show, handleMounted } } } </script>
内容的提问来源于stack exchange,提问作者Quốc Phan Chính
相关产品推荐
相关产品推荐

