首页 文章

vuejs更新子组件的父数据

提问于
浏览
66

我开始玩vuejs(2.0) . 我构建了一个包含一个组件的简单页面 . 该页面有一个带有数据的Vue实例 . 在那个页面上,我注册并将组件添加到html . 该组件有一个 input[type=text] . 我希望该值反映在父(主Vue实例)上 .

如何正确更新组件的父数据?从父级传递绑定的prop并不好,并向控制台发出一些警告 . 他们的文档中有一些东西,但它不起作用 .

5 回答

  • 75

    Vue 2.0中不推荐使用双向绑定,而是使用更多事件驱动的体系结构 . 一般来说,孩子不应该改变它的道具 . 相反,它应该$emit事件并让父母回应这些事件 .

    在您的特定情况下,您可以使用 v-model 自定义组件 . 这是一种特殊的语法,允许接近双向绑定的东西,但实际上是上述事件驱动架构的简写 . 你可以在这里阅读 - > https://vuejs.org/v2/guide/components.html#Form-Input-Components-using-Custom-Events .

    这是一个简单的例子:

    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 (value) {
          this.$emit('input', value);
        }
      }
    });
    
    new Vue({
      el: '#app',
      data: {
        parentValue: 'hello'
      }
    });
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
    
    <div id="app">
      <p>Parent value: {{parentValue}}</p>
      <child v-model="parentValue"></child>
    </div>
    
    <template id="child">
       <input type="text" v-bind:value="value" v-on:input="updateValue($event.target.value)">
    </template>
    

    文档说明了这一点

    <custom-input v-bind:value="something" v-on:input="something = arguments[0]"></custom-input>
    

    相当于

    <custom-input v-model="something"></custom-input>
    

    这就是为什么孩子的道具需要被命名为值,以及为什么孩子需要$发出一个名为 input 的事件 .

  • 3

    来自documentation

    在Vue.js中,父子组件关系可以概括为支持向下,事件向上 . 父母通过道具将数据传递给孩子,孩子通过事件向父母发送消息 . 让我们看看他们下一步如何运作 .

    enter image description here

    如何传递道具

    以下是将props传递给子元素的代码:

    <div>
      <input v-model="parentMsg">
      <br>
      <child v-bind:my-message="parentMsg"></child>
    </div>
    

    如何发出事件

    HTML:

    <div id="counter-event-example">
      <p>{{ total }}</p>
      <button-counter v-on:increment="incrementTotal"></button-counter>
      <button-counter v-on:increment="incrementTotal"></button-counter>
    </div>
    

    JS:

    Vue.component('button-counter', {
      template: '<button v-on:click="increment">{{ counter }}</button>',
      data: function () {
        return {
          counter: 0
        }
      },
      methods: {
        increment: function () {
          this.counter += 1
          this.$emit('increment')
        }
      },
    })
    new Vue({
      el: '#counter-event-example',
      data: {
        total: 0
      },
      methods: {
        incrementTotal: function () {
          this.total += 1
        }
      }
    })
    
  • 101

    在子组件中: this.$emit.('eventname', this.variable)

    在父组件中:

    <component @eventname="updateparent"></component>
    
    methods: {
        updateparent(variable) {
            this.parentvariable = variable
        }
    }
    
  • 0

    也可以将props作为Object或Array传递 . 在这种情况下,数据将是双向绑定的:

    (这在主题末尾注明:https://vuejs.org/v2/guide/components.html#One-Way-Data-Flow

    Vue.component('child', {
      template: '#child',
      props: {post: Object},
      methods: {
        updateValue: function () {
          this.$emit('changed');
        }
      }
    });
    
    new Vue({
      el: '#app',
      data: {
        post: {msg: 'hello'},
        changed: false
      },
      methods: {
        saveChanges() {
            this.changed = true;
        }
      }
    });
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
    
    <div id="app">
      <p>Parent value: {{post.msg}}</p>
      <p v-if="changed == true">Parent msg: Data been changed - received signal from child!</p>
      <child :post="post" v-on:changed="saveChanges"></child>
    </div>
    
    <template id="child">
       <input type="text" v-model="post.msg" v-on:input="updateValue()">
    </template>
    
  • 1

    我同意上述事件的事件发射和v模型答案 . 但是,我想我会发布我发现的有多个表单元素的组件,这些表单元素想要发回给他们的父级,因为这似乎是google返回的第一篇文章之一 .

    我知道这个问题指定了一个输入,但这似乎是最接近的匹配,可能会节省一些时间与类似的vue组件 . 此外,还没有人提到 .sync 修饰符 .

    据我所知, v-model 解决方案仅适用于返回其父级的一个输入 . 我花了一点时间寻找它,但Vue(2.3.0)文档确实展示了如何将发送到组件中的多个道具同步回父级(当然通过发射) .

    它被恰当地称为 .sync 修饰符 .

    这是documentation所说的:

    在某些情况下,我们可能需要对道具进行“双向绑定” . 不幸的是,真正的双向绑定可能会产生维护问题,因为子组件可能会改变父组件,而父组件和子组件中的突变源不明显 . 这就是为什么我们建议以update:myPropName模式发出事件 . 例如,在具有 Headers 道具的假设组件中,我们可以传达分配新值的意图:

    this.$emit('update:title', newTitle)
    

    然后父级可以监听该事件并更新本地数据属性(如果需要) . 例如:

    <text-document   
     v-bind:title="doc.title"  
     v-on:update:title="doc.title = $event"
    ></text-document>
    

    为方便起见,我们使用.sync修饰符为此模式提供简写:

    <text-document v-bind:title.sync="doc.title"></text-document>
    

    您还可以通过发送对象一次同步多个 . 看看documentation here

相关问题