VueJs与父组件属性对象

时间:2017-06-07 15:03:57

标签: vue.js vuejs2 vue-component

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

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

父组件

<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,但出于某种奇怪的原因{{1}当选择更改为:class="{ dn : fields.type_id == 2 }"时,不会附加课程dn。 Dom似乎没有反映父组件和子组件之间同步的更改。

有关如何使其有效的任何帮助?

2 个答案:

答案 0 :(得分:2)

以下是我试图在评论中提到的内容。 Vue cannot detect changes为动态添加到对象的属性,除非您使用$set添加它们。您的fields对象没有type_id属性,但由于您使用的是v-model="fields.type_id",因此会添加该属性。因此,Vue不知道它何时发生变化。

在这里,我添加了它,文本的颜色也随着你的预期而变化。

&#13;
&#13;
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
    }
  }
})
&#13;
.dn {
  color: red;
}
&#13;
<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>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

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

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

 <DifficultToUseSelect/>.

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

<select></select>

其他所有内容都由父组件管理。

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

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

    StateAbbrevsSelect v-model =&#34; state&#34;

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

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

同样,我在这里要传达的主要观点是,制作一个可重复使用的组件,其中超过一半的工作由父组件处理,实际上并不是非常可重复使用。