Vue js 动态导入组件

whi*_*993 4 javascript vue.js vue-component vuejs2

我有以下父组件,它必须呈现动态子组件列表:

<template>
  <div>
    <div v-for="(componentName, index) in supportedComponents" :key="index">
      <component v-bind:is="componentName"></component>
    </div>
   </div>
 </template>

<script>
const Component1 = () => import("/components/Component1.vue");
const Component2 = () => import("/components/Component2.vue");
export default {
  name: "parentComponent",
  components: {
    Component1,
    Component2
  },
  props: {
    supportedComponents: {
      type: Array,
      required: true
    }
  }
};
</script>
Run Code Online (Sandbox Code Playgroud)

supportedComponents属性是我想在父组件中呈现的组件名称列表。

为了使用父组件中的子组件,我必须导入它们并注册它们。

但唯一的方法是对组件的导入路径进行硬编码:

const Component1 = () => import("/components/Component1.vue");
const Component2 = () => import("/components/Component2.vue");
Run Code Online (Sandbox Code Playgroud)

然后像这样注册它们:

components: {
  Component1,
  Component2
}
Run Code Online (Sandbox Code Playgroud)

我想保持我的parentComponent尽可能通用。这意味着我必须找到一种方法来避免导入语句和注册中的硬编码组件路径。我想注入parentComponent它应该导入和渲染的子组件。

这在 Vue 中可能吗?如果是,那么如何?

Lau*_*max 6

您可以在创建的生命周期内加载组件并根据您的数组属性注册它们:

<template>
    <div>
        <div v-for="(componentName, index) in supportedComponents" :key="index">
            <component :is="componentName"></component>
        </div>
    </div>
</template>

<script>
    export default {
        name: "parentComponent",
        components: {},
        props: {
            supportedComponents: {
                type: Array,
                required: true
            }
        },
        created ()  {
            for(let c=0; c<this.supportedComponents.length; c++) {
                let componentName = this.supportedComponents[c];
                this.$options.components[componentName] = () => import('./' + componentName + '.vue');
            }
        }
    };
</script>
Run Code Online (Sandbox Code Playgroud)

效果很好


Mar*_*cRo 2

解决运行时动态 webpack import()

您可以动态设置函数的路径import()以根据组件状态加载不同的组件。

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

<script>
export default {
  props: {
    component: String,
  },

  data() {
    return {
      myComponent: '',
    };
  },

  computed: {
    loader() {
      return () => import(`../components/${this.component}`);
    },
  },

  created() {
    this.loader().then(res => {
      // components can be defined as a function that returns a promise;
      this.myComponent = () => this.loader();
    },
  },
}
</script>
Run Code Online (Sandbox Code Playgroud)

注意: JavaScript 在运行之前由浏览器编译。这与 webpack 导入的解析方式无关。