简体   繁体   English

Vue.js 父子组件动态双向数据绑定

[英]Vue.js dynamic two way data binding between parent and child components

I'm trying to use a combination of v-for and v-model to get a two-way data bind for some input forms.我正在尝试使用 v-for 和 v-model 的组合来为某些输入表单获取双向数据绑定。 I want to dynamically create child components.我想动态创建子组件。 Currently, I don't see the child component update the parent's data object.目前,我没有看到子组件更新父组件的数据对象。

My template looks like this我的模板看起来像这样

<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>

and the js this和 js 这个

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

new Vue({
  el: '#app',
  data: {
    ranges: [],
  },
  methods: {
    addRange: function () {
        this.ranges.push('')
    },
  }
})

I've also made a js fiddle as well https://jsfiddle.net/8mdso9fj/96/我也做了一个 js fiddle https://jsfiddle.net/8mdso9fj/96/

Note: the use of an array complicates things: you cannot modify an alias (the v-for variable).注意:使用数组会使事情复杂化:您不能修改别名(v-for 变量)。

One approach that isn't mentioned often is to catch the native input event as it bubbles up to the component .一种不经常提及的方法是在本地输入事件冒泡到组件时捕获它 This can be a little simpler than having to propagate Vue events up the chain, as long as you know there's an element issuing a native input or change event somewhere in your component.这可能比必须在链上传播 Vue 事件要简单一些,只要您知道在组件中的某处有一个元素发出本机inputchange事件。 I'm using change for this example, so you won't see it happen until you leave the field.我在这个例子中使用了change ,所以在你离开现场之前你不会看到它发生。 Due to the array issue, I have to use splice to have Vue notice the change to an element.由于数组问题,我必须使用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>

To use the .sync modifier , the child component has to emit an update: variablename event that the parent will catch and do its magic.要使用.sync修饰符,子组件必须发出一个update: variablename事件,父组件将捕获并发挥它的魔力。 In this case, variablename is data .在这种情况下,变量名data You still have to use the array-subscripting notation, because you still can't modify a v-for alias variable, but Vue is smart about .sync on the array element, so there's no messy splice .您仍然必须使用数组下标表示法,因为您仍然无法修改 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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM