6 个回答

感觉跟 defineAsyncComponent 有关系,组件还没加载出来,onMounted 已经执行完了。

不应该用getCurrentInstance拿当前组件实例吗

题目中的写法是对的,只不过拿到的引用是空的。

子组件需要明确使用expose方法暴露出接口之后,才能在父组件获取到接口引用。

未暴露接口的情况下,引用的始终是一个空对象。

// child.vue
<template>
  <div>child</div>
</template>
<script setup>
import { useContext } from "vue";
const { expose } = useContext(); // 通过context获取expose方法
const sayHi = ref('Hello world');
expose({
  sayHi // 明确的暴露接口
});
</script>
// parent.vue
<template>
  <div>I have a child</div>
  <Child ref="childRef" />
</template>
<script setup>
import { onMounted } from "vue";
import Child from "./child.vue"
const childRef = ref(null) // 子组件引用
onMounted(()=>{
  console.log(childRef.value); // => Proxy {sayHi: RefImpl}
  console.log(childRef.value.sayHi);  // => Hello world
})
</script>

vue3使用$refs ,可以通过vm = getCurrentInstance()拿到组件实例,然后在 vm.ctx.$refs 上找到对模板的引用。https://feizhaojun.com/?p=3355

在当前项目我使用的解法

<template>
  <component :is="componentId" ref="componentRef"></compoent>
</template>

<script lang="ts" setup>
  import { defineAsyncComponent, computed } from 'vue'
  const asyncFileComponent = defineAsyncComponent(() => import('./file.vue'))
  const asyncTableComponent = defineAsyncComponent(() => import('./table.vue'))

  const componentRef = ref<InstanceType<typeof asyncFileComponent> | InstanceType<typeof asyncTableComponent> | null>(null)
  const type = ref<string>('file')
  const componentId = computed(() => {
    if (type.value === 'file') return asyncFileComponent
    if (type.value === 'table') return asyncTableComponent
    else return null
  })

  const handleClick = () => {
    // 此时需要子组件都对外暴露 reload  方法
    componentRef.vlaue?.reload()
  }
</script>
注意 mounted 不会保证所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以在 mounted 内部使用 vm.$nextTick

v3也同样有这个提示,生命周期钩子 | Vue.js

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题