我正在尝试创建一个布局组件,它从一个或另一个列中的父级动态创建给定的组件。在布局组件中,我使用指令创建子组件。这是可行的,但是我很难将数据放入组件本身(它们有不同的属性集)。
因此:
如何将属性数据注入< component :is="componentFromParent“/>指令?
我有点事要做,但是很乱。我可以通过一个包含所有数据的"genericProps“属性来实现。然后强制子进程进行更新,然后通过updated()使用Object.assign(this, 'props', this.genericProps)解压genericProps并覆盖它的$props。
在这里,我感觉就像是在与vue.js的一些王子对抗。在调试时,布局组件的this.$options.components是填充的,但是所有这些组件都没有分配任何propsData。但是直接在this.$options.components上使用Object.assign()是行不通的,因为布局组件看起来像是这些组件的实际实例,因为它是this.$childrend。
此外,我还尝试了遍历this.$childrend并分配this.$options.components的propsData,但必须有一个键才能将组件与其正确的子级匹配,并且在这一点上,子级端没有填充任何属性。
代码片段来说明这个(丑陋的)示例,它有点像是在工作:
父模板
<template>
<two-column-layout :firstColumn="$vuetify.breakpoint.mdAndUp ? firstColumn : singleColumn"
:secondColumn="$vuetify.breakpoint.mdAndUp ? secondColumn : []"
/>
</template>上级代码
当来自API的异步调用完成时,通过mounted()或watch调用此代码。
createMetadataContent() {
let currentContent = this.currentMetadataContent;
const components = this.$options.components;
currentContent = this.mixinMethods_enhanceMetadataEntry(currentContent, this.cardBGImages);
if (currentContent && currentContent.title !== undefined) {
this.body = metaDataFactory.createBody(currentContent);
this.$set(components.MetadataBody, 'genericProps', this.body);
this.citation = metaDataFactory.createCitation(currentContent);
this.$set(components.MetadataCitation, 'genericProps', this.citation);
// a few more components and data here
this.firstColumn = [
components.MetadataBody,
// a few more components here
];
this.secondColumn = [
components.MetadataCitation,
// a few more components here
];
this.singleColumn = [
components.MetadataBody,
components.MetadataCitation,
// a few more components here
];
this.$forceUpdate();
}
}TwoColumnLayout模板
<template>
<v-layout row wrap>
<v-flex>
<v-layout column>
<v-flex mb-2
v-for="(entry, index) in firstColumn"
:key="`left_${index}`"
>
<component :is="entry"
:genericProps="entry.genericProps"
/>
</v-flex>
</v-layout>
</v-flex>
<v-flex v-if="secondColumn" >
<v-layout column>
<v-flex mb-2
v-for="(entry, index) in secondColumn"
:key="`right_${index}`"
>
<component :is="entry"
:genericProps="entry.genericProps"
/>
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</template>TwoColumnLayout代码
updated() {
this.$children.forEach((child) => {
child.$forceUpdate();
});
},下级代码
props: {
genericProps: Object,
id: String,
citationText: String,
citationXmlLink: String,
ciationIsoXmlLink: String,
ciationGCMDXmlLink: String,
fixedHeight: Boolean,
showPlaceholder: Boolean,
},
updated: function updated() {
if (this.genericProps) {
Object.assign(this, 'props', this.genericProps);
}
},发布于 2019-06-06 21:21:55
我可以通过插槽解决它,但我仍然需要在LayoutComponent中使用forceUpdate()……然而,对于我的情况,使用genericProps已经足够好了。
父模板
<template v-slot:leftColumn >
<div v-for="(entry, index) in firstColumn" :key="`left_${index}`" >
<component :is="entry" :genericProps="entry.genericProps" />
</div>
</template>
<template v-slot:rightColumn>
<div v-for="(entry, index) in secondColumn" :key="`right_${index}`" >
<component :is="entry" :genericProps="entry.genericProps" />
</div>
</template>
上级代码
当API的异步调用完成时,通过mounted()或通过watch调用此代码。
createMetadataContent() {
let currentContent = this.currentMetadataContent;
const components = this.$options.components;
currentContent = this.mixinMethods_enhanceMetadataEntry(currentContent, this.cardBGImages);
if (currentContent && currentContent.title !== undefined) {
this.body = metaDataFactory.createBody(currentContent);
this.$set(components.MetadataBody, 'genericProps', this.body);
this.citation = metaDataFactory.createCitation(currentContent);
this.$set(components.MetadataCitation, 'genericProps', this.citation);
// a few more components and data here
this.firstColumn = [
components.MetadataBody,
// a few more components here
];
this.secondColumn = [
components.MetadataCitation,
// a few more components here
];
this.singleColumn = [
components.MetadataBody,
components.MetadataCitation,
// a few more components here
];
this.$forceUpdate();
}
}TwoColumnLayout模板
<v-flex v-bind="firstColWidth" >
<v-layout column>
<slot name="leftColumn" />
</v-layout>
</v-flex>
<v-flex v-if="secondColumn" v-bind="secondColWidth" >
<v-layout column>
<slot name="rightColumn" />
</v-layout>
</v-flex>TwoColumnLayout代码
updated() {
this.$children.forEach((child) => {
child.$forceUpdate();
});
},下级代码
所有子组件都有genericProps对象,可以通过mixin方法访问该对象
props: {
genericProps: Object,
},
computed: {
title() {
return this.mixinMethods_getGenericProp('title');
},
id() {
return this.mixinMethods_getGenericProp('id');
},
description() {
return this.mixinMethods_getGenericProp('description');
},
}混入方法
mixinMethods_getGenericProp(propName) {
return this.genericProps[propName] ? this.genericProps[propName] : null;
},发布于 2019-03-22 16:00:05
我曾经有过一个类似的情况,我有一个动态的<compnonent :is="currentComponent">,并通过将“<compnonent :is="currentComponent"> passed”属性存储到我的数据中并将其作为道具传递给孩子来解决它。每当我的有效负载发生变化时,它就会在子进程中刷新。
<template>
<div>
<div class="btn btn-primary" @click="changePayload">Change Payload</div>
<component :is="isWhat" :payload="payload"></component>
</div>
</template>
<script>
export default {
name: "Test",
data() {
return {
isWhat: 'div',
payload: { any: 'data', you: 'want', to: 'pass'}
}
},
methods: {
changePayload() { // any method or api call can change the data
this.payload = { some: 'changed', data: 'here' }
}
}
}
</script>https://stackoverflow.com/questions/55263184
复制相似问题