25 - Componentes: eventos propios y captura en la instancia Vue

Una parte muy importante es la posibilidad de emitir eventos en la componente y luego poderlos capturar en la instancia Vue.

En la componente debemos llamar a $emit y pasar el nombre del evento que lo captura:

this.$emit(nombre del evento)

Veamos con un ejemplo como se codifican los eventos propios en una componente.

Problema

Crear una aplicación que muestre 3 componentes de la clase 'selector-numerico'. En la instancia Vue mostrar la suma de los tres selectores numéricos.

Para resolver este problema debemos modificar la componente 'selector-numerico' para que la instancia de la clase Vue se entere cuando cambia dicho selector:

<!doctype html>
<html>
<head>
  <title>Prueba Vue</title> 
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
</head>
<body>
  <div id="aplicacion">
    <selector-numerico v-on:incremento="sumar(1)" v-on:decremento="sumar(-1)" v-bind:valor="0" v-bind:minimo="0" v-bind:maximo="20"></selector-numerico>
    <selector-numerico v-on:incremento="sumar(1)" v-on:decremento="sumar(-1)" v-bind:valor="0" v-bind:minimo="0" v-bind:maximo="20"></selector-numerico>    
    <selector-numerico v-on:incremento="sumar(1)" v-on:decremento="sumar(-1)" v-bind:valor="0" v-bind:minimo="0" v-bind:maximo="20"></selector-numerico>    
    <p>La suma es:{{suma}}</p>
  </div>
 
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>

  Vue.component('selector-numerico', {
    props:['valor', 'minimo', 'maximo'],
    template: `<div><span style="width:1rem;display:inline-block;background:#ff0">{{cant}}</span>
                 <button v-on:click="incrementar()">+</button>
                 <button v-on:click="decrementar()">-</button>
               </div>`,
    data: function() {
      return {
        cant: this.valor
      }
    },
    methods: {
      incrementar: function() {
        if (this.cant<this.maximo) {
          this.cant++;
          this.$emit('incremento');
        }
      },
      decrementar: function() {
        if (this.cant>this.minimo) {
          this.cant--;
          this.$emit('decremento');
        }
      }      
    }
  })

  new Vue({
    el:'#aplicacion',
    data: {
      suma: 0
    },
    methods:{
        sumar:function(valor) {
          this.suma+=valor
        }
      }
  })

</script>
</body>
</html>

La suma es:{{suma}}

Cuando se presiona el botón incrementar de la componente se dispara el método 'incrementar' donde disparamos el evento 'incremento':

    methods: {
      incrementar: function() {
        if (this.cant<this.maximo) {
          this.cant++;
          this.$emit('incremento');
        }
      },

El evento 'incremento' se lo especifica en el HTML agregando la directiva v-on:

    <selector-numerico v-on:incremento="sumar(1)" v-on:decremento="sumar(-1)" v-bind:valor="0" v-bind:minimo="0" v-bind:maximo="20"></selector-numerico>

Al ser capturado el evento 'incremento' llamamos al método 'sumar' de la instancia Vue indicando que debe sumar 1 al contador de todos los selectores numéricos.

De forma muy similar capturamos el evento que resta 1 a un selector numérico y mediante un evento se entera el objeto de la clase Vue.

Tengamos en cuenta que cuando queremos enviar datos a una componente se lo hace a través de propiedades y cuando queremos recuperar datos de una componente lo hacemos mediante la emisión de eventos.

Ejecutar Ejemplo

Retornar