按名称盲动态加载 vuejs 组件和属性



我想在 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>

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中指定。按需加载组件(异步组件(。

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

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

演示

而不是直接导入组件,您可以使用如下所示的import包装它们

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

<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>
// removed imports
export default {
components: {
Title: () => import('@/components/libs/Title.vue'),
Status: () => import('@/components/libs/Status.vue'),
Carousel: () => import('@/components/libs/Carousel.vue')
},
}
</script>

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

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>

响应是否始终包含这些字段?您想在 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>

自定义组件

<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>

最新更新