从 Vue 2 中的列表动态导入组件

问题描述 投票:0回答:1

我有一个门户网站,它以 vue 组件的形式提供不同的服务。我们将服务的所有设置保存在数据库中(包括存储该服务的路径 (=pfad))。通过这些数据,我们提供了应加载的所有活动服务的列表(有 50 多个服务,因此我们不想每次添加新服务时都编写新的导入)。

如果一个服务文件不存在,它也应该捕获错误(我们正在与多人一起开发这个工具,因此一个人会在数据库中声明一项新服务,但仅在他的功能分支上)。

我在

ServiceMain.vue
尝试了以下解决方案,但是导入的服务没有挂载。

HTML部分:

<template>
    <b-row>
        <b-col>
            <!--Visible Services need the Service-Box so the user can click it. Import of the Service happens in teh Service-Box-->
            <div>
                <service-box v-for="service in filteredServices.slice((rowIdx - 1) * 3, rowIdx * 3)" :key="service.id"
                    :service="service" />
            </div>
            <!--Invisible Services should only get a component tag, they should not be visible to the user-->
            <div
                v-if="invisibleServices.length > 0"
                style="!important display: none;">
                <component
                    :is="componentFile"
                    v-for="(componentFile, index) in componentFilesOfInvisibleServices"
                    :key="'invisibleComponent_' + index"
                />
            </div>
        </b-col>
    </b-row>
</template>

脚本部分:

export default {
    name: "ServicesMain",
    // components: {...},
    data: function () {
        return {
            services: [],
            visibleServices: [],
            invisibleServices: [],
        };
    },
    computed: {
        componentFilesOfInvisibleServices() {
            let files = [];
            for (const invisibleService of this.invisibleServices) {
                let componentName = invisibleService.pfad;
                try {
                    let componentFile = import(`@/components/dialogs/${componentName}.vue`);
                    files.push(componentFile);
                } catch (e) {
                    // later handel the Error if a file is not found
                    console.error(e)
                }
            }
            return () => files;
        },
    },
    mounted() {
        this.getServices();
    },
    methods: {
        getServices() {
            ticketApi
                .getTicketTypes()
                .then(response => {
                    this.services = response.data;
                    this.visibleServices = response.data.filter(service => service.isVisible);
                    this.invisibleServices = response.data.filter(service => !service.isVisible && service.parentTicket === undefined);
                    // ...
                })
                .catch(error => {
                    console.error(error);
                });
        }
    }
};
</script>

如果我使用在 :is="..." 中加载模块的函数,我会遇到无限循环

我还在 stackoverflow 上搜索并找到了以下线程,但没有一个对我有用或有解决方案。

Vue-动态导入vue组件

在Vue功能组件中使用动态导入

动态导入vue组件解析失败

这个解决方案理论上可行,但它是在没有过滤的情况下导入所有内容,我们需要在 vue-script 部分中过滤 te 组件的选项。

在 Vue JS 中的组件内自动导入组件

vue.js vuejs2 vue-component
1个回答
0
投票

代码存在多个问题,以下解决方案适合我: HTML 部分不需要编辑。计算属性“componentFilesOfInvisibleServices”可以被删除,相反我们需要“componentFilesOfInvisibleServices”作为数据中的空数组。以下方法应该在其他代码之后的 then 块中的“getServices”中调用。

async loadComponentFilesOfInvisibleServices() {

  this.componentFilesOfInvisibleServices = await Promise.all(
      this.invisibleServices.map(async (service) => {
        let componentName = service.pfad.substring(service.pfad.lastIndexOf('$') + 1);

        const module =  await import(`@/components/dialogs/${componentName}.vue`);
        this.$options.components[componentName] = module.default;

        return module;
      })
  );
},

我还需要在返回之前将“.default”添加到模块中,以便返回组件的默认值。

作为说明,在使用“.default”之前,我收到一条错误消息:

组件挂载失败:模板或渲染函数未定义

检查“模块”后,我认为您还必须使用“.default”。

© www.soinside.com 2019 - 2024. All rights reserved.