首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >vue:将属性数据动态注入<component />

vue:将属性数据动态注入<component />
EN

Stack Overflow用户
提问于 2019-03-20 22:28:46
回答 2查看 2K关注 0票数 0

我正在尝试创建一个布局组件,它从一个或另一个列中的父级动态创建给定的组件。在布局组件中,我使用指令创建子组件。这是可行的,但是我很难将数据放入组件本身(它们有不同的属性集)。

因此:

如何将属性数据注入< 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.componentspropsData,但必须有一个键才能将组件与其正确的子级匹配,并且在这一点上,子级端没有填充任何属性。

代码片段来说明这个(丑陋的)示例,它有点像是在工作:

父模板

代码语言:javascript
复制
<template>
  <two-column-layout :firstColumn="$vuetify.breakpoint.mdAndUp ? firstColumn : singleColumn"
                      :secondColumn="$vuetify.breakpoint.mdAndUp ? secondColumn : []"
                      />
</template>

上级代码

当来自API的异步调用完成时,通过mounted()或watch调用此代码。

代码语言:javascript
复制
  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模板

代码语言:javascript
复制
<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代码

代码语言:javascript
复制
updated() {
  this.$children.forEach((child) => {
    child.$forceUpdate();
  });
},

下级代码

代码语言:javascript
复制
  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);
    }
  },
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-06 21:21:55

我可以通过插槽解决它,但我仍然需要在LayoutComponent中使用forceUpdate()……然而,对于我的情况,使用genericProps已经足够好了。

父模板

代码语言:javascript
复制
  <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调用此代码。

代码语言:javascript
复制
  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模板

代码语言:javascript
复制
    <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代码

代码语言:javascript
复制
updated() {
  this.$children.forEach((child) => {
    child.$forceUpdate();
  });
},

下级代码

所有子组件都有genericProps对象,可以通过mixin方法访问该对象

代码语言:javascript
复制
    props: {
      genericProps: Object,
    },
    computed: {
      title() {
        return this.mixinMethods_getGenericProp('title');
      },
      id() {
        return this.mixinMethods_getGenericProp('id');
      },
      description() {
        return this.mixinMethods_getGenericProp('description');
      },
    }

混入方法

代码语言:javascript
复制
    mixinMethods_getGenericProp(propName) {
      return this.genericProps[propName] ? this.genericProps[propName] : null;
    },
票数 0
EN

Stack Overflow用户

发布于 2019-03-22 16:00:05

我曾经有过一个类似的情况,我有一个动态的<compnonent :is="currentComponent">,并通过将“<compnonent :is="currentComponent"> passed”属性存储到我的数据中并将其作为道具传递给孩子来解决它。每当我的有效负载发生变化时,它就会在子进程中刷新。

代码语言:javascript
复制
<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>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55263184

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档