You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3(Quasar)中使用Composition API实现动态组件失败求助

Vue3(Quasar)Setup语法糖中动态组件无法渲染问题

可正常运行的Options API代码

<template>
  <p>
    <button @click="component = 'ComponentA'">Comp A</button>
    <button @click="component = 'ComponentB'">Comp B</button>
  </p>

  <component :is="component" />
</template>

<script>
import ComponentA from "../components/ComponentA.vue";
import ComponentB from "../components/ComponentB.vue";

export default {
  components: {
    ComponentA,
    ComponentB,
  },
  data() {
    return {
      component: "ComponentA",
    };
  },
};
</script>

无法正常工作的Setup语法糖代码

<template>
  <q-page class="flex column flex-center background-white">
    <q-btn @click="component = 'ComponentA'"
      >ComponentA</q-btn
    >
    <q-btn @click="component = 'ComponentB'"
      >ComponentB</q-btn
    >
    <component :is="component" />
  </q-page>
</template>
<script setup>
import { ref, defineAsyncComponent } from "vue";

const component = ref("ComponentA");

const ComponentA = defineAsyncComponent(() =>
  import("../components/ComponentA.vue")
);
const ComponentB = defineAsyncComponent(() =>
  import("../components/ComponentB.vue")
);
</script>

问题原因

在Setup语法糖中,局部声明的组件不会自动注册为模板可通过字符串名称访问的组件。而Options API里的components选项会把组件注册到当前实例,因此可以用字符串名称引用组件;你现在直接把字符串'ComponentA'绑定到:is上,模板无法找到对应的组件引用,导致渲染失败。

两种解决方案

方案1:直接绑定组件引用

将ref的初始值和点击事件的赋值改为组件本身的引用:

<template>
  <q-page class="flex column flex-center background-white">
    <q-btn @click="component = ComponentA">ComponentA</q-btn>
    <q-btn @click="component = ComponentB">ComponentB</q-btn>
    <component :is="component" />
  </q-page>
</template>
<script setup>
import { ref, defineAsyncComponent } from "vue";

const ComponentA = defineAsyncComponent(() =>
  import("../components/ComponentA.vue")
);
const ComponentB = defineAsyncComponent(() =>
  import("../components/ComponentB.vue")
);

// 直接将ref初始化为组件引用
const component = ref(ComponentA);
</script>

方案2:创建组件映射表

如果希望保留字符串名称的使用方式,可以创建映射表,将字符串对应到组件引用:

<template>
  <q-page class="flex column flex-center background-white">
    <q-btn @click="component = 'ComponentA'">ComponentA</q-btn>
    <q-btn @click="component = 'ComponentB'">ComponentB</q-btn>
    <!-- 通过映射表获取组件引用 -->
    <component :is="componentMap[component]" />
  </q-page>
</template>
<script setup>
import { ref, defineAsyncComponent } from "vue";

const component = ref("ComponentA");

const ComponentA = defineAsyncComponent(() =>
  import("../components/ComponentA.vue")
);
const ComponentB = defineAsyncComponent(() =>
  import("../components/ComponentB.vue")
);

// 创建字符串到组件的映射表
const componentMap = {
  ComponentA,
  ComponentB
};
</script>

内容的提问来源于stack exchange,提问作者acroscene

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 20:44:53