【问题标题】:VueJs reactivity with parent component property objectVueJs 对父组件属性对象的反应性
【发布时间】:2017-11-09 00:36:38
【问题描述】:

我很难获取父组件的属性对象,动态填充属性以使值在同一组件内可用。

有点难解释,请看下面的例子:

父组件

<script>
    export default {
        data() {
            return {
                fields: {},
            }
        }
    }
</script>

子组件

<template>
  <select
      @change="update()"
      v-model="field"
  >
      <option
          v-for="option in options"
          :value="option.value"
      >
          {{ option.name }}
      </option>
  </select>
</template>
<script>
    export default {
        props: {
            initialOptions: {
                type: Array,
                required: true
            }
        },
        data() {
            return {
                    field: '',
                options: this.initialOptions
            }
        },
        mounted() {
            if (
                (this.field === undefined || this.field === '') &&
                this.options.length > 0
            ) {
                this.field = this.options[0].value;
            }
            this.update();
        },
        methods: {
            update() {
                this.$emit('input', this.field);
            }
        }
    }
</script>

DOM

<parent-component inline-template>

    <div>

        <child-component>           
            :initial-options="[{..}, {..}]"
          v-model="fields.type_id"
        ></child-component>

    </div>

    <div :class="{ dn : fields.type_id == 2 }">

        // ...

    </div>

</parent-component>

使用 Vue 控制台,我可以看到 fields 对象获取所有子组件模型及其关联值,因为它们在挂载时发出 input,但是由于某些奇怪的原因,:class="{ dn : fields.type_id == 2 }" 没有附加该类dn when the selection changes to 2. Dom 似乎没有反映父组件和子组件之间同步的更改。

关于如何使它工作的任何帮助?

【问题讨论】:

  • 你是如何向父fields添加属性的?
  • 在子组件上使用 v-model 指令并在 mounted 上使用来自每个子组件的关联值发出 input 事件。
  • 你能展示一下吗?我得到的是fields 开始是一个空对象。如果您错误地添加属性,那么 Vue 将无法检测到更改。
  • 在上面的例子中 - 请检查Child Component部分然后DOM子组件得到v-model。你会看到在mounted 上有一个对update() 方法的调用,它会发出事件。
  • fields: {} 何时/如何获得名为 type_id 的属性?

标签: vue.js vuejs2 vue-component


【解决方案1】:

这是我试图在 cmets 中得到的。 Vue cannot detect changes 用于动态添加到对象的属性,除非您使用 $set 添加它们。您的fields 对象没有type_id 属性,但它被添加是因为您使用的是v-model="fields.type_id"。因此,Vue 不知道什么时候发生变化。

在这里,我已经添加了它,并且文本的颜色会按照您的预期发生变化。

console.clear()

Vue.component("child-component", {
  template: `
    <select
        @change="update()"
        v-model="field"
    >
        <option
            v-for="option in options"
            :value="option.value"
        >
            {{ option.name }}
        </option>
    </select>
  `,
  props: {
    initialOptions: {
      type: Array,
      required: true
    }
  },
  data() {
    return {
      field: '',
      options: this.initialOptions
    }
  },
  mounted() {
    if (
      (this.field === undefined || this.field === '') &&
      this.options.length > 0
    ) {
      this.field = this.options[0].value;
    }
    this.update();
  },
  methods: {
    update() {
      this.$emit('input', this.field);
    }
  }
})

new Vue({
  el: "#app",
  data: {
    fields: {
      type_id: null
    }
  }
})
.dn {
  color: red;
}
<script src="https://unpkg.com/vue@2.2.6/dist/vue.js"></script>
<div id="app">
  <div>
    <child-component :initial-options="[{name: 'test', value: 1}, {name: 'test2', value: 2}]" v-model="fields.type_id"></child-component>
  </div>
  <div :class="{ dn : fields.type_id == 2 }">
    Stuff
  </div>
</div>

【讨论】:

  • 太遗憾了,因为这样我总是不得不通过 props 将它们传递给父控制器 - 所有这些都绝对没有充分的理由。
【解决方案2】:

看起来您正在尝试制作可重用的组件。

我会问自己,当父组件必须处理一半以上的工作时,可重用组件的价值是什么。该组件可能会更好地命名...

 <DifficultToUseSelect/>.

本质上,您正在创建一个组件,它自己提供以下所有 HTML...

<select></select>

其他一切都由父组件管理。

执行以下任何操作可能会更有用...

  • 在特定的选择组件中封装经常需要的选项,如

    StateAbbrevsSelect v-model="state"

  • 将数据模型的名称传递给选择组件。然后组件将通过模型加载和管理自己的数据。

  • 将 Web 服务的 URL 传递给组件,然后调用该组件来加载其选项。

再一次,我想在这里表达的主要观点是,制作一个可重用的组件,其中一半以上的工作由父组件处理,实际上并不是很可重用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-09
    • 2020-11-12
    • 2017-11-03
    • 2018-11-02
    • 2021-11-24
    • 2017-11-24
    • 2020-10-03
    • 1970-01-01
    相关资源
    最近更新 更多