Vuejs:如何将对象作为prop传递并使组件更新子对象

时间:2018-03-02 15:59:13

标签: vue.js vuejs2

我正在尝试创建一个接受对象作为prop的组件,并且可以使用sync或emit事件修改该对象的不同属性并将值返回给父对象。这个例子不起作用,但它只是为了展示我想要实现的目标。

这是我想要实现的内容的片段:



<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>

<div id="app">
  <p>Parent value: {{parentObject}}</p>
  <child v-model="parentObject"></child>
</div>

<template id="child">
   <input type="text" v-bind:value.value1="value" v-on:input="updateValue($event.target.value)">
   <input type="text" v-bind:value.value2="value" v-on:input="updateValue($event.target.value)">
</template>
&#13;
select  (2299) / (((2299) * 20 )/ (100 * 360)) from dual;
&#13;
&#13;
&#13;

4 个答案:

答案 0 :(得分:4)

您不应该修改作为道具传入的对象。相反,您应该在子组件中创建一个新的数据属性,并使用prop对象的副本对其进行初始化。

然后,我只对子组件中的每个输入使用v-model,并为内部值添加一个深度观察器,每当内部值发生变化时,它将发出update

Vue.component('child', {
  template: '#child',
  props: ['value'],
  data() {
    return { val: {...this.value} };
  },
  watch: {
    val: {
      deep: true,
      handler(value) {
        this.$emit('input', value);
      }
    }
  }
});

new Vue({
  el: '#app',
  data: {
    parentObject: {value1: "1st Value", value2: "2nd value"}
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>

<div id="app">
  <p>Parent value: {{parentObject}}</p>
  <child v-model="parentObject"></child>
</div>

<template id="child">
  <div>
    <input type="text" v-model="val.value1">
    <input type="text" v-model="val.value2">
  </div>
</template>

我在我的示例({...this.value})中制作了一个浅的副本,因为该对象没有任何嵌套属性。如果不是这种情况,您可能需要进行深层复制(JSON.parse(JSON.stringify(this.value)))。

答案 1 :(得分:2)

#app中,shoudld为parentObject,而不是parentValue

在孩子中,你有两个inpyt,但你必须有一个根元素。在下面的示例中,我为组件创建了一个<div>根元素。

要更新父级,请发出事件。这种方法不会修改子项中父项的属性,因此不会破坏单向数据流。

Vue.component('child', {
  template: '#child',
  
  //The child has a prop named 'value'. v-model will automatically bind to this prop
  props: ['value']
});

new Vue({
  el: '#app',
  data: {
    parentObject: {value1: "1st Value", value2: "2nd value"}
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>

<div id="app">
  <p>Parent value: {{parentObject}}</p>
  <child v-model="parentObject"></child>
</div>

<template id="child">
<div>
   <input type="text" v-bind:value="value.value1" v-on:input="$emit('input', {value1: $event.target.value, value2: value.value2})">
   <input type="text" v-bind:value="value.value2" v-on:input="$emit('input', {value1: value.value1, value2: $event.target.value})">
</div>
</template>

关于<input>:您可以将每个绑定到父value的属性。然后,在编辑时,发出一个事件,仅修改该属性(v-on:input="$emit('input', {value1: $event.target.value, value2: value.value2}))并保留另一个值。父母因此而更新。

如果您有许多属性,则可以在第二个input中替换,例如:

$emit('input', {value1: value.value1, value2: $event.target.value})

使用

$emit('input', Object.assign({}, value, {value2: $event.target.value}))


使用方法而不是直接从模板

发出

我保留了之前的演示,因为它更直接,更简单(比原始代码更少),但更简洁的方法是使用方法(例如updateValue)并在模板:

Vue.component('child', {
  template: '#child',
  
  //The child has a prop named 'value'. v-model will automatically bind to this prop
  props: ['value'],
  methods: {
    updateValue: function(propertyName, propertyValue) {
      this.$emit('input', Object.assign({}, this.value, {[propertyName]: propertyValue}))
    }
  }
});

new Vue({
  el: '#app',
  data: {
    parentObject: {value1: "1st Value", value2: "2nd value"}
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>

<div id="app">
  <p>Parent value: {{parentObject}}</p>
  <child v-model="parentObject"></child>
</div>

<template id="child">
<div>
  <input type="text" v-bind:value="value.value1" v-on:input="updateValue('value1', $event.target.value)">
  <input type="text" v-bind:value="value.value2" v-on:input="updateValue('value2', $event.target.value)">
</div>
</template>

如您所见,上面的演示已使用Object.assign(),这意味着它将处理无限数量的属性。

答案 2 :(得分:0)

<TradeTableItem v-for="(debtReserve, index) in debtReserves" :key="debtReserve.id" :debtReserve="debtReserve" :market="market" :id="'order_by_' + index"></TradeTableItem>

在上一步中,我们为每一行生成了id。

然后在TradeTableItem(您要填充的模板,表格行)中,将id编写为:id =“ this.id”,其中this.id是道具的一部分。

希望这会有所帮助

答案 3 :(得分:0)

不使用props的另一种方法可能是访问子组件中的组件属性$attrs

在父母中

<child v-model="parentObject" />

在子级中,v-model生成的value属性可以在模板中以以下方式访问

$attrs.value.value1

这是反应性的。

演示HERE