我开始玩vuejs(2.0)。
我构建了一个包含一个组件的简单页面。
该页面有一个带有数据的Vue实例。
在那个页面上,我注册并将组件添加到html。
该组件有一个input[type=text]
。我希望该值反映在父(主Vue实例)上。
如何正确更新组件的父数据? 从父级传递绑定的prop并不好,并向控制台发出一些警告。他们的文档中有一些东西,但它不起作用。
答案 0 :(得分:123)
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>
&#13;
文档声明
<custom-input v-bind:value="something" v-on:input="something = arguments[0]"></custom-input>
相当于
<custom-input v-model="something"></custom-input>
这就是为什么孩子的道具需要被命名为值,以及为什么孩子需要$发出名为input
的事件。
答案 1 :(得分:92)
在Vue.js中,父子组件关系可以概括为道具向下,事件向上。父母通过道具将数据传递给孩子,孩子通过事件向父母发送消息。让我们看看他们接下来的工作方式。
以下是将道具传递给子元素的代码:
<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
}
}
})
答案 2 :(得分:19)
在子组件中:
this.$emit('eventname', this.variable)
在父组件中:
<component @eventname="updateparent"></component>
methods: {
updateparent(variable) {
this.parentvariable = variable
}
}
答案 3 :(得分:4)
我同意上述事件的发出事件和v模型的答案。但是,我想我会发布我发现的有关具有多个表单元素的组件的信息,这些组件想要发回给它们的父对象,因为这似乎是google返回的第一篇文章之一。
我知道问题指定了单个输入,但是这似乎是最接近的匹配,并且可以通过使用类似的vue组件为人们节省一些时间。另外,还没有人提到.sync
修饰符。
据我所知,v-model
解决方案仅适用于一个返回其父级的输入。我花了一些时间寻找它,但是Vue(2.3.0)文档确实显示了如何将发送到组件中的多个道具同步回父对象(当然是通过发出)。
它被适当地称为.sync
修饰符。
documentation的意思是:
在某些情况下,我们可能需要对道具进行“双向绑定”。 不幸的是,真正的双向绑定会造成维护问题, 因为子组件可以在没有源的情况下改变父组件 这种变异在父母和孩子中都很明显。
这就是为什么我们建议以以下方式发出事件:
update:myPropName
。例如,在具有title
道具,我们可以交流分配新值的意图 与:
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
答案 4 :(得分:3)
也可以将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;
}
}
});
&#13;
<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>
&#13;
答案 5 :(得分:1)
子组件
使用this.$emit('event_name')
将事件发送到父组件。
父组件
为了在父组件中侦听该事件,我们执行v-on:event_name
,并在该事件上执行要执行的方法(ex. handleChange
)
完成:)
答案 6 :(得分:1)
在孩子中
<input
type="number"
class="form-control"
id="phoneNumber"
placeholder
v-model="contact_number"
v-on:input="(event) => this.$emit('phoneNumber', event.target.value)"
/>
data(){
return {
contact_number : this.contact_number_props
}
},
props : ['contact_number_props']
在父级
<contact-component v-on:phoneNumber="eventPhoneNumber" :contact_number_props="contact_number"></contact-component>
methods : {
eventPhoneNumber (value) {
this.contact_number = value
}
答案 7 :(得分:1)
2021 答案 - Vue 2.3+
简短回答:只需在父级中添加 .sync
修饰符并将数据作为道具传递给子级:
// PARENT:
data () {
return {
formData: {
members: [] //<- we wanna pass this one down to children and add/remove from the child component
}
}
// PARENT TEMPLATE:
<!-- ADD MEMBERS -->
<add-members :members.sync="formData.members" />
嵌套子组件:AddMembers.vue
export default {
name: 'AddMembers',
props: ['members'],
methods: {
addMember () {
this.members.push(new Member()) // <-- you can play and reactivity will work (in the parent)
},
removeMember (index) {
console.log('remove', index, this.members.length < 1)
this.members.splice(index, 1)
}
}
}
长话短说:实际上,子组件的更改正在 $emitted 并更新父组件的 dataForm.memmbers[]。
答案 8 :(得分:0)
更简单的方法是使用heightAnchor
Father.vue
this.$emit
Child.vue
<template>
<div>
<h1>{{ message }}</h1>
<child v-on:listenerChild="listenerChild"/>
</div>
</template>
<script>
import Child from "./Child";
export default {
name: "Father",
data() {
return {
message: "Where are you, my Child?"
};
},
components: {
Child
},
methods: {
listenerChild(reply) {
this.message = reply;
}
}
};
</script>
我的完整示例:https://codesandbox.io/s/update-parent-property-ufj4b
答案 9 :(得分:0)
正确的方法是$emit()
an event in the child component that the main Vue instance listens for。
resolvers += Resolver.url("my-test-repo", new java.net.URL("https://dl.bintray/blocke/releases"))(Resolver.mavenStylePatterns)
答案 10 :(得分:0)
我不知道为什么,但是我只是使用数据作为对象:set
和computed
Parent.vue
<!-- check inventory status - component -->
<CheckInventory :inventory="inventory"></CheckInventory>
data() {
return {
inventory: {
status: null
},
}
},
Child.vue
<div :set="checkInventory">
props: ['inventory'],
computed: {
checkInventory() {
this.inventory.status = "Out of stock";
return this.inventory.status;
},
}
答案 11 :(得分:0)
他的示例将告诉您如何在“提交”按钮上将输入值传递给父项。
首先将eventBus定义为新的Vue。
//main.js
import Vue from 'vue';
export const eventBus = new Vue();
Pass your input value via Emit.
//Sender Page
import { eventBus } from "../main";
methods: {
//passing data via eventbus
resetSegmentbtn: function(InputValue) {
eventBus.$emit("resetAllSegment", InputValue);
}
}
//Receiver Page
import { eventBus } from "../main";
created() {
eventBus.$on("resetAllSegment", data => {
console.log(data);//fetching data
});
}
答案 12 :(得分:0)
我认为这可以解决问题:
@change="$emit(variable)"
答案 13 :(得分:0)
在父级中->
data : function(){ return { siteEntered : false, }; },
在子组件中->
this.$parent.$data.siteEntered = true;
答案 14 :(得分:0)
我正在寻找在 vue3 中从父级到子级(并返回)发送数据(我知道问题是关于 vue2,但当时在 SO 上没有关于 vue3 的参考)。
以下是工作样板结果,纯“html + js”,没有打包程序、模块等,我有一些警告,解释。
<component-a :foo="bar" @newfooevent="bar = $event"></component-a>`
我使用简写 parent.bar
将 child.foo
绑定到 :foo="bar"
,与 v-bind:foo="bar"
相同。它通过 props 将数据从 parent 传递给 child。
警告:事件侦听器应仅放置在子组件标记中!
那是 @newfooevent="bar = $event"
部分。
您无法在 <div id="app">
或父级内部的任何其他地方捕获信号。
尽管如此,这是宇宙的父方,在这里您可以访问所有父的数据并从子信号中提取数据进行处理。
您可以创建应用程序,并在其之后定义组件(app.component("component-a", ...)
部分。
警告:不需要组件的前向声明,例如C/C++ 中的函数。您可以创建使用该组件的应用程序,然后定义该组件。我花了很多时间寻找以某种方式声明它的方法 - 没有必要。
您可以在此处找到一个很好的 v-model
用法示例,以及我用来解决问题的代码:https://javascript.plainenglish.io/vue-3-custom-events-d2f310fe34c9
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<meta charset="utf-8" />
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<component-a :foo="bar" @newfooevent="bar = $event"></component-a>
<p>Parent copy of `bar`: {{ bar }}</p>
<button @click="bar=''">Clear</button>
</div>
<script>
const app = Vue.createApp({
data() {
return {
bar: "bar start value"
};
}
});
app.component("component-a", {
props: {
foo: String
},
template: `
<input
type="text"
:value="foo"
@input="$emit('newfooevent', $event.target.value)">
`
});
app.mount("#app");
</script>
</body>
</html>
答案 15 :(得分:-1)
另一种方法是将设置器的引用作为属性从父级传递给子级组件,类似于他们在React中的操作。
假设您在父级上有一个方法updateValue
用于更新值,您可以像这样{@ {1}}来实例化子级组件。然后在孩子上,您将有一个对应的道具:<child :updateValue="updateValue"></child>
,并且在输入更改为props: {updateValue: Function}
时在模板中调用方法。