vuejs 从子组件更新父数据

IT技术 javascript vue.js vue-component
2021-02-01 18:33:21

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

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

6个回答

双向绑定在 Vue 2.0 中已被弃用,以支持使用更多事件驱动的架构。一般来说,一个孩子不应该改变它的props。相反,它应该$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>

这就是为什么孩子上的props需要命名为 value,以及为什么孩子需要 $emit 一个名为input.

首先感谢您的回复。你能扩展一下,或者更好地指向关于“输入”事件的文档吗?这似乎是一个内置的事件。
2021-03-12 18:33:21
没有违规。父级绑定value到子级。这意味着value孩子道具将匹配父母道具。孩子只读取这个值,从不直接更新它。当用户写入文本时,子级会发出一个具有最新值(方法updateValue的事件为了响应该事件,父更新value反过来,这会导致value更新孩子道具。
2021-03-12 18:33:21
我添加了一个说明,并使文档的链接更加明显。
2021-03-25 18:33:21
我省略了组件和创建的函数的道具“值”,但它仍然有效。你能解释一下你为什么使用它吗?
2021-03-31 18:33:21
如果你不添加道具,那么它会undefined一直到第一次改变。看到这个我已经注释掉的小提琴props: ['value']注意初始值是undefined,而不是hellojsfiddle.net/asemahle/8Lrkfxj6第一次更改后,Vue 动态地为组件添加了一个 value 属性,因此它可以工作。
2021-04-07 18:33:21

在子组件中:

this.$emit('eventname', this.variable)

在父组件中:

<component @eventname="updateparent"></component>

methods: {
    updateparent(variable) {
        this.parentvariable = variable
    }
}
难的是要简单。太感谢了!为什么其他冗长的答案使它变得如此复杂。
2021-03-14 18:33:21
@Sarvar Nishonboev - 当 updateparent 方法更新父变量时,它是否“自动”将其作为道具传递回子变量?
2021-03-28 18:33:21
这个例子简直让我大吃一惊。你不知道在我来到这里之前我经历了多少教程......
2021-04-04 18:33:21
@veritas - 不,在这种情况下不是,因为子组件不接收父变量作为道具。如果有,那就会了。
2021-04-05 18:33:21
这个例子比其他例子最棒。
2021-04-05 18:33:21

文档

在Vue.js中,父子组件关系可以概括为props down,events up。父级通过 props 将数据传递给子级,子级通过事件向父级发送消息。接下来让我们看看它们是如何工作的。

在此处输入图片说明

如何传递props

以下是将 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
    }
  }
})
我会打印那个图形并贴在我的头上。谢谢!
2021-03-18 18:33:21
在这个例子中,我们不应该在根组件中定义一个事件监听器吗?类似:```mounted() { this.on('increment', () => { this.incrementTotal(); }); }```
2021-03-19 18:33:21
掌握概念的剪切时刻,尽管已经通过hacky copy paste多次使用它......
2021-03-21 18:33:21
如果函数“增量”在父组件中并且我想从子组件触发它怎么办?
2021-04-05 18:33:21

子组件

用于this.$emit('event_name')向父组件发送事件。

在此处输入图片说明

父组件

为了在父组件中监听那个事件,我们做v-on:event_name了一个ex. handleChange我们想要在那个事件上执行的方法 ( )

在此处输入图片说明

完毕 :)

我同意上面那些的事件发射和 v-model 答案。但是,我想我会发布我发现的关于具有多个表单元素的组件的内容,这些元素想要发送回其父级,因为这似乎是 google 返回的第一篇文章之一。

我知道这个问题指定了一个输入,但这似乎是最接近的匹配,并且可能会为人们节省一些使用类似 vue 组件的时间。此外,还没有人提到.sync修改器。

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

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

这是什么 文档中的内容

在某些情况下,我们可能需要对 prop 进行“双向绑定”。不幸的是,真正的双向绑定会产生维护问题,因为子组件可以对父组件进行变异,而该变异的来源在父组件和子组件中都不明显。

这就是为什么相反,我们建议以 update:myPropName. 例如,在一个带有titleprop的假设组件中 ,我们可以通过以下方式传达分配新值的意图:

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>

您还可以通过发送一个对象一次同步多个。此处查看文档

这就是我一直在寻找的。非常感谢。
2021-03-11 18:33:21
这是截至 2020 年最好和最新的解决方案。非常感谢!
2021-03-31 18:33:21