VueJS met à jour les données parent à partir du composant enfant
Je commence à jouer avec vuejs (2.0).
J'ai construit une page simple avec un composant dedans.
La page a une instance Vue avec des données.
Sur cette page, j'ai enregistré et ajouté le composant html.
Le composant a un input[type=text]
. Je veux que cette valeur reflète sur le parent (instance principale Vue).
Comment mettre à jour correctement les données parentes du composant? Passer un accessoire lié du parent n'est pas bon et lance quelques avertissements à la console. Ils ont quelque chose dans leur doc mais ce n'est pas le cas travailler.
4 réponses
La liaison bidirectionnelle a été dépréciée dans Vue 2.0 en faveur d'une architecture plus axée sur les événements. En général, un enfant ne devrait pas muter ses accessoires. Au contraire, il devrait $emit
événements et laisser le parent répondre à ces événements.
Dans votre cas particulier, vous pouvez utiliser un composant personnalisé avec v-model
. C'est une syntaxe spéciale qui permet quelque chose de proche de la liaison bidirectionnelle, mais est en fait un raccourci pour l'architecture pilotée par les événements décrite ci-dessus. Vous pouvez lire à ce sujet il ici - > https://vuejs.org/v2/guide/components.html#Form-Input-Components-using-Custom-Events .
Voici un exemple simple:
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>
Les documents indiquent que
<custom-input v-bind:value="something" v-on:input="something = arguments[0]"></custom-input>
Est équivalent à
<custom-input v-model="something"></custom-input>
C'est pourquoi l'hélice sur l'enfant doit être nommé de la valeur, et pourquoi l'enfant a besoin de $émettent un événement nommé input
.
En Vue.js, la relation de composant parent-enfant peut être résumée comme des accessoires vers le bas, des événements vers le haut. Le parent transmet des données à l'enfant via des accessoires, et l'enfant envoie des messages au parent via des événements. Voyons comment ils fonctionnent ensuite.
Comment passer des accessoires
Voici le code pour passer des accessoires à un élément enfant:
<div>
<input v-model="parentMsg">
<br>
<child v-bind:my-message="parentMsg"></child>
</div>
Comment émettre événement
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
}
}
})
Il est également possible de passer des accessoires en tant Qu'objet ou Tableau. Dans ce cas, les données seront liées dans les deux sens:
(Ceci est noté à la fin du sujet: 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>
Dans le composant enfant:
this.$emit.('eventname', this.variable)
Dans le composant parent:
<component @eventname="updateparent"></component>
methods: {
updateparent(variable) {
this.parentvariable = variable
}
}