Vue 3 动态加载异步组件

Gio*_*ung 6 typescript vue.js

我想根据组件的类型显示它。让我解释。

我有多个彼此相似的组件,但根据给定的类型,它们应该显示不同的内容。通过该defineAsyncComponent方法,我可以导入组件并轻松使用它们。例子:

const CheckboxControl = defineAsyncComponent(
  () => import('@/components/editor/controls/CheckboxControl.vue'),
);
Run Code Online (Sandbox Code Playgroud)

这工作正常,但如果我这样做,我就会有大量的导入组件。我不想要这个。我的方法是将defineAsyncComponent箭头函数包装在内部,如下所示:

const loadComponent = async (type: string) =>
  defineAsyncComponent(
    () =>
      import(
        `@/components/editor/controls/${type[0].toUpperCase()}${type.substring(
          1,
        )}Control.vue`
      ),
  );
Run Code Online (Sandbox Code Playgroud)

在模板中,我可以像这样渲染组件<component :is="renderComponent(control.type)" />

但这给了我以下警告:

[Vue warn]: Component is missing template or render function.
Run Code Online (Sandbox Code Playgroud)

等待defineAsyncComponent方法并不能解决问题。

我究竟做错了什么?如何动态导入这些组件?

更新

以下是属性内部的所有可能性control.type

  • 复选框
  • 日期
  • 电子邮件
  • 数字
  • 收音机
  • 范围
  • 选择
  • 文本区域
  • 文本

更新2

这是我当前正在运行的代码:

const CheckboxControl = defineAsyncComponent(
  () => import('@/components/editor/controls/CheckboxControl.vue'),
);

const DateControl = defineAsyncComponent(
  () => import('@/components/editor/controls/DateControl.vue'),
);

const EmailControl = defineAsyncComponent(
  () => import('@/components/editor/controls/EmailControl.vue'),
);

const NumberControl = defineAsyncComponent(
  () => import('@/components/editor/controls/NumberControl.vue'),
);

const RadioControl = defineAsyncComponent(
  () => import('@/components/editor/controls/RadioControl.vue'),
);

const RangeControl = defineAsyncComponent(
  () => import('@/components/editor/controls/RangeControl.vue'),
);

const SelectControl = defineAsyncComponent(
  () => import('@/components/editor/controls/SelectControl.vue'),
);

const TextareaControl = defineAsyncComponent(
  () => import('@/components/editor/controls/TextareaControl.vue'),
);

const TextControl = defineAsyncComponent(
  () => import('@/components/editor/controls/TextControl.vue'),
);

const loadComponent = (type: string) => {
  switch (type) {
    case 'checkbox':
      return CheckboxControl;
    case 'date':
      return DateControl;
    case 'email':
      return EmailControl;
    case 'number':
      return NumberControl;
    case 'radio':
      return RadioControl;
    case 'range':
      return RangeControl;
    case 'select':
      return SelectControl;
    case 'textarea':
      return TextareaControl;
    case 'text':
      return TextControl;
    default:
      // TODO: show error component if type not supported
      break;
  }
};
Run Code Online (Sandbox Code Playgroud)

更新3

对于我当前的设置,我使用 vite 作为构建工具。我用的vite版本是2.9.5. 我使用的 vue 版本是3.2.33和 typescript 版本4.6.3

Gio*_*ung 5

感谢@Estus Flask 的帮助:)

所以问题是我试图用别名导入它@。我将我的方法更改为:

const loadComponent = (type: string) =>
  defineAsyncComponent(
    () =>
      import(
        `./controls/${type[0].toUpperCase()}${type.substring(1)}Control.vue`
      ),
  );
Run Code Online (Sandbox Code Playgroud)

现在这有效了。

我不知道为什么在这种情况下它不能与@别名一起使用,因为当我在中使用它时它可以工作

const CheckboxControl = defineAsyncComponent(
  () => import('@/components/editor/controls/CheckboxControl.vue'),
);
Run Code Online (Sandbox Code Playgroud)

也许有人对此有解释?