我正在尝试创建一个布局组件,该组件可以动态地从一个或另一列中的父级创建给定的组件。在布局组件中,我使用指令创建子组件。可以,但是我很难将数据放入组件本身(它们具有不同的属性集)。
因此:
我有一些工作要做,但这很混乱。我可以通过包含所有数据的“ genericProps”属性来实现。然后强迫孩子进行更新,他们通过updated()
使用Object.assign(this, 'props', this.genericProps)
解压缩genericProps
并覆盖$props
。
感觉好像我正在对付vue.js的某些原理。调试时会填充布局组件的this.$options.components
,但是所有这些组件都没有分配任何propsData
。但是直接在Object.assign()
上使用this.$options.components
是行不通的,因为布局组件实际上是this.$childrend
上这些组件的实际实例。
我也尝试遍历this.$childrend
的{{1}}并分配propsData
,但是必须有一个密钥来匹配具有正确子元素的组件,并且指出子级没有任何属性。
代码片段说明了可以工作的(丑陋的)示例:
this.$options.components
从API异步调用完成后,可通过mount()或通过watch调用此代码。
<template>
<two-column-layout :firstColumn="$vuetify.breakpoint.mdAndUp ? firstColumn : singleColumn"
:secondColumn="$vuetify.breakpoint.mdAndUp ? secondColumn : []"
/>
</template>
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();
}
}
<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>
updated() {
this.$children.forEach((child) => {
child.$forceUpdate();
});
},
答案 0 :(得分:0)
我曾经有过类似的情况,我有一个动态<compnonent :is="currentComponent">
并通过存储数据的'childPayload'属性并将其作为道具传递给孩子来解决。每当我的有效载荷发生变化时,它们的子项就会刷新。
<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>
答案 1 :(得分:0)
我可以通过插槽来解决它,但是我仍然需要在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();
}
}
<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>
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;
},