带有属性的名称盲的动态加载vuejs组件

时间:2020-01-08 17:04:09

标签: vue.js vue-component

我想在vuejs CLI中动态加载组件作为单个文件组件, 在ajax请求之前,我不知道将加载哪个组件,也无法在页面加载时加载150个组件。

以下是ajax响应的示例:

[
  {is="Title", text:"Hello World"},
  {is:"Status", type:"info", text:"Look at these beautiful photos"},
  {is:"Carousel", imgs:["/img/1.jpg","/img/2.jpg","/img/3.jpg"]},
  {is:"Status", type:"alert", text:"These images are the property of the creator"},
]

我想要一个渲染如下的vue组件:

<template>
  <component is="Title" text="Hello World"/>
  <component is="Status" type="info" text="Look at these beautiful photos"/>
  <component is="Carousel" imgs="['/img/1.jpg','/img/2.jpg','/img/3.jpg']"/>
  <component is="Status" type="alert", text="These images are the property of the creator"/>
</template>
<script>
    import Title from '@/components/libs/Title.vue'
    import Status from '@/components/libs/Status.vue'
    import Carousel from '@/components/libs/Carousel.vue'
    export default {
        components: {
            Title,
            Status,
            Carousel
        },
    }
</script>

4 个答案:

答案 0 :(得分:2)

App.vue

<template>
  <div id="app">
    <DynamicComponentSet :definition="response"/>
  </div>
</template>

<script>
import DynamicComponentSet from "@/components/DynamicComponentSet";

export default {
  name: "App",
  components: {
    DynamicComponentSet
  },
  data() {
    return {
      response: [
        { is: "Title", text: "Hello World" },
        { is: "Status", type: "info", text: "Look at these beautiful photos" },
        { is: "Carousel", imgs: ["/img/1.jpg", "/img/2.jpg", "/img/3.jpg"] },
        {
          is: "Status",
          type: "alert",
          text: "These images are the property of the creator"
        }
      ]
    };
  }
};
</script>

DynamicComponentSet.vue

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

<script>
export default {
  name: "DynamicComponentSet",
  components: {
    Title: () => import("@/components/Title.vue"),
    Status: () => import("@/components/Status.vue"),
    Carousel: () => import("@/components/Carousel.vue")
  },
  props: {
    definition: Array
  }
};
</script>

注1:必须在is中指定所有可能的components值。组件按需加载(async components)。

注2:所有response对象的属性都使用props as an object语法通过v-bind="comp"传递到各个组件中,因此数据属性名称/类型必须与每个组件属性匹配。 / p>

注3:实际上:is="comp.is"并不需要使它起作用,因为is与其他道具一起被传递了。我补充说只是为了让ESLint开心...

demo

答案 1 :(得分:1)

您可以像下面这样用world.cities包装它们,而不是直接导入组件

这只会在实际需要时从服务器加载(从服务器)

import

答案 2 :(得分:1)

不是使用计算的方法动态导入组件。

    computed: {
        Title() {
            return () => import('@/components/libs/Title.vue');
        },
        Status() {
            return () => import('@/components/libs/Status.vue');
        }
    },

在模板中

    <component v-bind:is="Title"></component>
    <component v-bind:is="Status"></component>

答案 3 :(得分:0)

响应将始终包含那些字段吗?您要在ajax请求之前加载组件吗?喜欢默认值吗?

父组件

<template>
  <CustomComponent :responseData="Title" />
</template>
<script>
    import CustomComponent from '@/components/libs/CustomComponent.vue'
    export default {
        components: {
            CustomComponent
        },
        data() {
          return {
            responseData: null, // populate this with ajax response
          }
        }
    }
</script>

CustomComponent

<template>
  <div> <!-- components should only have one root element so wrap in a div -->
    <p v-if="response.text">{{ response.text }}</p>
    <p type="info">Look at these beautiful photos<p/>
    <!-- etc. etc. -->
  </div>
</template>
<script>
    import Status from '@/components/libs/Status.vue'
    import Carousel from '@/components/libs/Carousel.vue'
    export default {
        props: {
          responseData: {
            text: 'default text', // these defaults allow you to load before the ajax response comes in
            images: ['/img/1.jpg','/img/2.jpg','/img/3.jpg'],
          }
        },
        components: {
            Status,
            Carousel
        },
    }
</script>