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.

61
demandé sur coffee-grinder 2016-12-01 19:16:13

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.

92
répondu asemahle 2018-04-06 00:37:00

De la documentation :

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.

entrez la description de l'image ici

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
    }
  }
})
69
répondu Saurabh 2018-03-31 23:34:29

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>
0
répondu Perlovka 2018-03-23 23:50:50

Dans le composant enfant: this.$emit.('eventname', this.variable)

Dans le composant parent:

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

methods: {
    updateparent(variable) {
        this.parentvariable = variable
    }
}
0
répondu Sarvar Nishonboyev 2018-09-09 10:15:50