Composants Vue.js - Événements personnalisés

Les composants parents utilisent des props pour transmettre des données aux composants enfants, mais si un composant enfant doit renvoyer des données, des événements personnalisés sont nécessaires !

Nous pouvons utiliser v-on pour lier des événements personnalisés. Chaque instance Vue implémente l'interface d'événements (Events interface), c'est-à-dire :

  • Utiliser$on(eventName)Écouter les événements
  • Utiliser$emit(eventName)Déclencher des événements

De plus, le composant parent peut utiliser v-on directement là où le composant enfant est utilisé pour écouter les événements déclenchés par le composant enfant.

Dans l'exemple suivant, le composant enfant est complètement découplé de l'extérieur. Tout ce qu'il fait, c'est déclencher un événement interne qui intéresse le composant parent.

Exemple

<div id="app"> <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> </div> <script> Vue.component('button-counter', { template: '<button v-on:click="incrementHandler">{{ counter }}</button>', data: function () { return { counter: 0 } }, methods: { incrementHandler: function () { this.counter += 1 this.$emit('increment') } }, }) new Vue({ el: '#counter-event-example', data: { total: 0 }, methods: { incrementTotal: function () { this.total += 1 } } }) </script>

Essayez-le »

Si vous souhaitez écouter un événement natif sur l'élément racine d'un composant, vous pouvez utiliser le modificateur .native sur v-on. Par exemple :

<my-component v-on:click.native="doTheThing"></my-component>

data doit être une fonction

Dans l'exemple ci-dessus, vous pouvez voir que la propriété data du composant button-counter n'est pas un objet, mais une fonction :

data: function () {
  return {
    count: 0
  }
}

L'avantage est que chaque instance peut maintenir une copie indépendante de l'objet retourné. Si data est un objet, cela affectera les autres instances, comme montré ci-dessous :

Exemple

<div id="components-demo3" class="demo"> <button-counter2></button-counter2> <button-counter2></button-counter2> <button-counter2></button-counter2> </div> <script>var buttonCounter2Data = { count: 0 } Vue.component('button-counter2', { /* data: function () { // l'option data est une fonction, les composants ne s'affectent pas mutuellement return { count: 0 } }, */ data: function () { // l'option data est un objet, affectera les autres instances return buttonCounter2Data }, template: '<button v-on:click="count++">Cliqué {{ count }} fois.</button>' }) new Vue({ el: '#components-demo3' }) </script>

Essayez-le »

v-model pour les composants personnalisés

Par défaut, v-model sur un composant utilise la prop nommée value et l'événement nommé input.

<input v-model="parentData">

Équivalent à :

<input 
    :value="parentData"
    @input="parentData = $event.target.value"
>

Dans l'exemple suivant, le composant personnalisé example-input est défini. La valeur initiale de num dans le composant parent est 100. Modifier la valeur dans le composant enfant peut mettre à jour le num du composant parent en temps réel :

Exemple

<div id="app"> <example-input v-model="num"></example-input> <p>Le nombre saisi est : {{num}}</p> </div> <script> Vue.component('example-input', { template: ` <p> <!--Contient l'événement nommé input--> <input ref="input" :value="value" @input="$emit('input', $event.target.value)" > </p>`, props: ['value'], // prop nommée value }) new Vue({ el: '#app', data: { num: 100, } })</script>

Essayez-le »

Parce que v-model transmet value par défaut, et non checked, pour les composants de type case à cocher ou bouton radio, nous devons utiliser l'option model. L'option model peut spécifier le type d'événement actuel et les props transmises.

Exemple

<div id="app"> <base-checkbox v-model="lovingVue"></base-checkbox> <div v-show="lovingVue">Si la case à cocher est cochée, je serai affiché.</div> </div> <script>// Enregistrement Vue.component('base-checkbox', { model: { prop: 'checked', event: 'change' // événement onchange }, props: { checked: Boolean }, template: `<input type="checkbox" v-bind:checked="checked" v-on:change="$emit('change', $event.target.checked)" >` }) // Créer l'instance racine new Vue({ el: '#app', data: { lovingVue: true } })</script>

Essayez-le »

Dans l'exemple, la valeur de lovingVue est passée à la prop checked, et lorsque <base-checkbox> déclenche l'événement change, la valeur de lovingVue est également mise à jour.

Autres extensions