Vue.js父和子组件之间的动态双向数据绑定

时间:2017-09-04 22:20:59

标签: javascript vue.js components vuejs2 vue-component

我尝试使用v-for和v-model的组合来获取某些输入表单的双向数据绑定。我想动态创建子组件。目前,我没有看到子组件更新父级的数据对象。

我的模板看起来像这样

[

和js这个

<div class="container" id="app">
  <div class="row">
    Parent Val
    {{ ranges }}
  </div>

   <div class="row">
     <button 
        v-on:click="addRange"
        type="button" 
        class="btn btn-outline-secondary">Add time-range
     </button>
    </div>

  <time-range 
    v-for="range in ranges"
    :box-index="$index"
    v-bind:data.sync="range">
  </time-range>

</div>

<template id="time-range">
  <div class="row">
    <input v-model="data" type="text">
  </div>
</template>

我也做了一个js小提琴[{3}}

1 个答案:

答案 0 :(得分:3)

注意:使用数组会使事情变得复杂:您无法修改别名(v-for变量)。

经常没有提到的一种方法是catch the native input event as it bubbles up to the component。这可能比必须在链中传播Vue事件更简单,只要您知道元素在组件中的某个位置发出本机inputchange事件即可。我在这个例子中使用change,因此在离开现场之前你不会看到它。由于数组问题,我必须使用splice让Vue注意到元素的更改。

Vue.component('time-range', {
  template: '#time-range',
  props: ['data']
})

new Vue({
  el: '#app',
  data: {
    ranges: [],
  },
  methods: {
  	addRange: function () {
    	this.ranges.push('')
    },
  }
})
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div class="container" id="app">
  <div class="row">
    Parent Val
    {{ ranges }}
  </div>
  
   <div class="row">
     <button 
        v-on:click="addRange"
        type="button" 
        class="btn btn-outline-secondary">Add time-range
     </button>
    </div>

  <time-range 
    v-for="range, index in ranges"
    :data="range"
    :key="index"
    @change.native="(event) => ranges.splice(index, 1, event.target.value)">
  </time-range>
</div>

<template id="time-range">
  <div class="row">
    <input :value="data" type="text">
  </div>
</template>

要使用the .sync modifier,子组件必须发出update: variablename 事件,父母将捕获并发挥其魔力。在这种情况下, variablename data。您仍然必须使用数组下标表示法,因为您仍然无法修改v-for别名变量,但Vue对数组元素上的.sync很聪明,因此没有杂乱的splice

Vue.component('time-range', {
  template: '#time-range',
  props: ['data'],
  methods: {
    emitUpdate(event) {
      this.$emit('update:data', event.target.value);
    }
  }
})

new Vue({
  el: '#app',
  data: {
    ranges: [],
  },
  methods: {
  	addRange: function () {
    	this.ranges.push('')
    },
  }
})
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div class="container" id="app">
  <div class="row">
    Parent Val
    {{ ranges }}
  </div>
  
   <div class="row">
     <button 
        v-on:click="addRange"
        type="button" 
        class="btn btn-outline-secondary">Add time-range
     </button>
    </div>

  <time-range 
    v-for="range, index in ranges"
    :data.sync="ranges[index]"
    :key="index">
  </time-range>

</div>

<template id="time-range">
  <div class="row">
    <input :value="data" type="text" @change="emitUpdate">
  </div>
</template>