Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Comunicación entre Componentes: eventos

18/38
Recursos

Aportes 32

Preguntas 8

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

HOLA! Vengo del futuro! presten atención a esta clase. La van a necesitar para quitar la visibilidad un modal hijo enviando el estado al dom padre.

Acá les dejo documentación para que amplien este concepto:

https://es.vuejs.org/v2/guide/components.html#Enviando-mensajes-a-componentes-padre-con-eventos

Suerte!

Cuando el componente hijo debe enviar información al componente padre, se deben enviar eventos, ya que las propiedades del componente padre nunca deben ser actualizadas por el componente hijo.
.
La comunicación de padres hacia hijos es a través de propiedades y la comunicación entre hijos hacia padres es a través de eventos.
.
v-on para enviar eventos hacia el componente padre.
.
$emit pertenece al core de VueJS permite indicar que el componente debe de emitir un evento.

this.$emit('nombre-del-evento')

En el HTML dentro de nuestro componente hijo agregamos la directiva v-on para indicar que esté escuchando el evento:

<coin-detail v-on:nombre-del-evento="funcion-a-ejecutar"</coin-detail>

Cada componente es totalmente aislado, es por ello que es importante que la función data sea una función que devuelva un objeto, de esta forma podemos garantizar que cada componente tiene su propio estado y que cuando se modifica este estado no se va a modificar el estado de otra instancia de este mismo componente. Si no fuera una función no seriamos capaces de mantener una referencia aislada de cada uno de nuestros componentes.

COMUNICACIÓN ENTRE COMPONENTES: EVENTOS (Clase 18)

¿Qué debemos hacer cuando un componente hijo necesita enviar información a un componente padre? Lo que debemos hacer es enviar eventos. Las propiedades del componente padre nunca deben ser actualizadas por el componente hijo. En caso de que haya que modificar una de estas propiedades, el componente hijo tiene que notificar al padre y esta notificación se hace a través de eventos. Se puede decir entonces que la comunicación de padre a hijo es con propiedades y de hijos a padres es con eventos. De esta manera mantenemos la consistencia en Vue.js.

Recordemos que usamos el v-bind para modificar en tiempo real o tener un atributo dinámico en cuanto a las propiedades y vamos a usar la emisión de eventos con la directiva v-on para que el componente hijo pueda enviar información al componente padre.

Tomando el código de la clase precedente, lo que vamos a hacer ahora es modificar la variable color del componente padre usando el componente hijo. El componente hijo debe emitir un evento para avisarle al componente padre.

Vamos a hacerlo con la función this.$emit(‘change-color’) inserta en la función toggleShowPrices() que está en methods del componente hijo.

methods: {
    toggleShowPrices() {
      this.showPrices = !this.showPrices;
      this.$emit('change-color')
     }
  },

Luego, en el Html , en <coin-detai> insertamos la directiva v-on: change-color=”updateColor ” (Significa: escuchar al evento change-color)

coin-detail 
    v-on:change-color="updateColor"
    v-bind:coin="btc"
    >  </coin-detail>

Ahora, en el componente principal (el padre) se define, en este ejemplo, el comportamiento de change-color, así:

methods:{
updateColor(){
  this.color = this.color.split('').reverse().join('')
    }
  }
})

Al momento de emitir un evento también podemos emitir un valor que vaya acompañando ese evento. En el argumento de la función this.$emit(‘change-color’) colocaremos el color que queremos, asi:

methods: {
    toggleShowPrices() {
      this.showPrices = !this.showPrices;
      this.$emit('change-color', 'ff96C8')
     }
  },

Luego en el componente principal podríamos cambiar el método updateColor() así:

methods:{
updateColor(color){
  this.color = color || this.color
  .split('').reverse().join('')
     }
   }
})

De esta manera el color va a ser siempre ‘ff96C8’ (color rosa). Una variante que podríamos hacer es esta:

methods: {
    toggleShowPrices() {
      this.showPrices = !this.showPrices;
      this.$emit('change-color', 
      this.showPrices ? 'ff96C8' : '3d3d3d')
     }
  },


Ahora bien, si repito el componente <coin-detail> de la forma como se ve enseguida, cada <coin-detail> se va a comportar de manera aislada. Por eso es importante que la función que tenemos dentro de data sea justamente una función que devuelva un objeto. Si en lugar de una función tuviésemos un objeto no seríamos capaces de mantener una referencia aislada para cada componente. De esta forma podemos garantizar que cada componente tiene su propio estado y que cuando se modifica el estado de un componente, por más que sea el mismo tipo de componente, no se va a modificar el estado del otro.

<div id="app" v-bind:style="{background: '#'+ color}">

    <coin-detail 
    v-on:change-color="updateColor"
    v-bind:coin="btc"
    >  </coin-detail>

    <coin-detail 
    v-on:change-color="updateColor"
    v-bind:coin="btc"
    >  </coin-detail>

    <coin-detail 
    v-on:change-color="updateColor"
    v-bind:coin="btc"
    >  </coin-detail>

  </div>

        - La comunicación de PADRES -> HIJOS debe ser con propiedades

            - Se utiliza PROPS para recibir los objetos del componente padre
            - props: ['variableDelPadre']

        - La comunicación de HIJOS -> PADRES debe ser con eventos

            - Se utiliza this$emit('unNombreParaElEvento') en JS
            - Se utiliza v-on:un-nombre-para-el-evento="nombreDelEventoPadre" en HTML

un componente padre se comunica con un componente hijo a travez de propiedades.

un componente hijo se comunica con un componente padre a travez de eventos.

Para mantener consistencia en Vue.js, la comunicación de padres hacia hijos debe ser por medio de propiedades y de hijos hacia padres por medio de eventos.

Con esta clase se me viene unas ideas para hacer un Dark Theme 😄 de una página

el final -> 🤯

Resumen de la clase

$emit('functionName','Paremeter')

Comunicación entre Componentes: Eventos

Para enviar información de un componente hijo a un componente padre es necesario enviar eventos.

Se debe de tener en cuenta que las propiedades que pertenecen al componente padre NUNCA deben ser actualizadas por el componente hijo; si se necesitara modificar alguna de éstas propiedades, el componente hijo tiene que modificar al padre, ésta notificación se realiza a través de eventos.

Se puede decir que la comunicación de padres hacia hijos es a través de Propiedades y la comunicación de hijos hacia padres es a través de Eventos, de ésta forma se mantiene la consistencia de cómo se utilizan las cosas en VueJS. V-bind se utiliza para modificar en tiempo real, o tener un atributo dinámico respecto a las propiedades y se utiliza la emisión de eventos con v-on para que el componente hijo pueda enviar información al componente padre.

$emit pertenece al Core de VueJS, se le indica al componente que emita un evento(En éste caso change-color) cada vez que se ejecuta el método(En éste caso el método toggleShowPrices).

methods: {
    toggleShowPrices () {
      this.showPrices = !this.showPrices

      this.$emit('change-color')
    }
},

Mientras tanto del lado del HTML se utiliza la directiva v-on para que escuche y así cache el evento(En éste caso change-color), solamente falta definir la función que se encargará de manejar el evento(En éste caso change-color).

<coin-detail 
      v-on:change-color="updateColor"
      v-bind:coin="btc"
></coin-detail>

Y en los métodos del componente padre:

updateColor () {
      this.color = this.color
        .split('')
        .reverse()
        .join('')
}

Cuando trabajamos con eventos, al emitir un evento es posible también emitir un valor que acompañe a ese evento. Para el ej. EN lugar de utilizar un reverse del color, se podría decirle al componente padre cuál es el color que tiene que utilizar.

this.$emit('change-color', 
        this.showPrices ? 'FF96C8' : '3D3D3D'
)
updateColor (color) {
      this.color = color || this.color
        .split('')
        .reverse()
        .join('')
}

Al utilizar componentes, es importante tener en cuenta que estos son fáciles de repetir o reutilizar a lo largo del código. Si se duplican los componentes, se tendrían varios componentes que tienen la misma funcionalidad, pero que son totalmente aislados, y por lo mismo es importante que la función que se tiene dentro de data devuelva un objeto, si en lugar de una función que devuelve un objeto, se tuviera un objeto, no seríamos capaces de mantener una referencia aislada para cada uno de los componentes. De ésta forma se garantiza que cada componente tiene su propio estado y que cuando se modifica el estado de un componente, no importando que sea el mismo tipo de componente, no se va a modificar el estado del otro.

Esto lo entendí de la siguiente manera:

Con la comunicación entre componentes a través de eventos es posible comunicar un componente hijo con su componente padre mediante un evento definido el cual al ejecutarse a su vez llamará a una función que cambiará el comportamiento de una propiedad del componente padre.

Aporten correcciones, mejora u opiniones.

Por cierto Ignacio gracias por explicar tan bien.

Como sería la actualización desde el padre cuando se emita un evento desde un componente hijo
que se debe actualizar
cuando se tiene una colección el estilo:

..
persons : [
	{name : "name-1"},
	{name : "name-2"},
	{name : "name-3"}
]

Consejo:

No usen camelCase para definir el nombre del evento a emitir. La sintaxis correcta para definir el nombre del evento es kebab-case. De lo contrario no importa que uses en tu HTML, el evento no se emite.

En esta clase lo que vamos hacer es que el componente hijo emita un evento para avisarle al componente padre que tiene que actualizar ese valor

Comunicación entre padres a hijos es a través de propiedades
Comunicación entre hijos a padres es a través de eventos

Algún viajero que ya haya visto el curso y esté pasando nuevamente por acá sabe si en algún momento del curso se utiliza algo parecido a un botón que agregue dinámicamente un formulario? O sabe si con lo visto hasta ahora se podría hacer? Le vengo dando vueltas y no me sale. Si alguien está dispuesto a darme una mano me vendría genial.

Comunicación entre Componentes: eventos

Las propiedades que pertenecen al componente padre nunca deben ser actuliazadas por el componete hijo. El hijo debe notificar al padre con eventos.

Podemos decir que la comunicación de padre a hijo es a través de propiedades y de hijo a padre es a través de eventos.

Eventos personalizados con $emit

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Primera Vue</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div
    id="app"
    v-bind:style="{ background: '#' + color }">

    <coin-detail
      v-on:change-color="updateColor"
      v-bind:coin="btc"
    >
    </coin-detail>

  </div>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
  <script src="app.js"></script>
</body>
</html>
Vue.component('coinDetail', {
  props: ['coin'], //*Pertenecen al componente 'padre'
  data() {
    return {
      showPrices: false,
      value: 0,
    }
  },
  methods: {
    toggleShowPrices() {
      this.showPrices = !this.showPrices

      this.$emit('change-color',
      this.showPrices ? 'FF96C8' : '3D3D3D') //*Segundo parametro es el color que tiene que utilizar el componente padre
    }
  },
  computed: {
    title () {
      return `${this.coin.name} - ${this.coin.symbol}`
    },

    convertedValue () {
      if(!this.value){
        return 0
      }
      return this.value / this.coin.price
    }
  },
  template: `
    <div>
      <img
        v-on:mouseover="toggleShowPrices"
        v-on:mouseout="toggleShowPrices"
        v-bind:src="coin.img"
        v-bind:alt="coin.name"
      >

      <h1
        v-bind:class="coin.changePercent > 0 ? 'green' : 'red'">
        {{ title }}
        <span v-if="coin.changePercent > 0">🤑</span>
        <span v-else>🤯</span>
        <button v-on:click="toggleShowPrices">
          {{ showPrices? '🙈' : '🐵' }}
        </button>
      </h1>

      <input type="number" v-model="value">
      <span>{{ convertedValue }}</span>

      <ul v-show="showPrices">
        <li
          class="uppercase"
          v-bind:class="{
            green: p.value > coin.price,
            orange: p.value === coin.price,
            red: p.value < coin.price,
          }"
          v-for="(p, index) in coin.pricesWithDays"
          v-bind:key="p.day">
          {{ index }} - {{ p.day }} - {{ p.value }}
        </li>
      </ul>
    </div>
  `
})

new Vue({
  el: '#app',

  data() {
    return {
      btc: {
        name: 'Bitcoin',
        symbol: 'BTC',
        img: 'https://cryptologos.cc/logos/bitcoin-btc-logo.png',
        changePercent: 10,
        price: 8400,
        pricesWithDays: [
          { day: 'Lunes', value: 8400 },
          { day: 'Martes', value: 7900 },
          { day: 'Miercoles', value: 8200 },
          { day: 'Jueves', value: 9000 },
          { day: 'Viernes', value: 9400 },
          { day: 'Sabado', value: 10000 },
          { day: 'Domingo', value: 10200 },
        ],
      },
      color: 'f4f4f4',
    }
  },

  methods: {
    updateColor(color) {
      this.color = color || this.color.split('').reverse().join('');
    }
  }
});

18.-Comunicación entre Componentes: eventos

Para mandar información de componente hijo a padre enviamos eventos, es importante tener en cuenta que las propiedades que pertenecen al componente padre NUNCA deben ser actualizadas por el hijo, en caso de que tengan que ser actualizadas el hijo debe notificar al padre, esta notificación se hace a través de eventos.

Padres → Hijos: Propiedades.

Hijos → Padres: Eventos.

Es importante que la función dentro de data sea una que devuelve un objeto, si solo fuera un objeto no podríamos mantener aislados cada uno de los componentes, así se garantiza que cada componente tiene su propio estado.

Ese momento en el que descubres que fue buena idea prestar atención en la clase de programación orientada a objetos en la Universidad

muy buena clases

Brutal!

Hola
Cual es el repositorio github del curso?

woooow! me impresiona mucho este framework.

nota: la comunicacion de padres hacia hijos es a traves de propiedades y de hijos hacia padre es a traves de eventos

super clase, excelente profe

tengo un problema me marca error en consola y No me muestra nada en el navegador,
" InvalidCharacterError: String contains an invalid character"

En mi laboratorio, intenté hacer un emit sin nomenclatura kebab hice lo adjunté bien todo pero no anduvo. No fue hasta que puse el naming en kebab que ahi comenzó a funcionar el emit.

Para la comunicación de hijos a padres se usan eventos que podemos usar a través de v-on, y podemos repetir los componentes tantas veces queramos.

De hecho lo increíble es que si nos copiamos el código del componente y nos los llevamos a cualquier otro proyecto, va a seguir funcionando exactamente igual, mientras tenga Vue enlazado.

Con los props podemos enviar información de un componente padre a un componente hijo. Para hacerlo al revés, de hijo a padre, se usan los eventos.

Las propiedades que pertenecen al componente padre nunca deben ser modificadas por el hijo

En caso de que alguna propiedad se tenga que modificar, el componente hijo le notificará al padre que una propiedad debe ser actualizada mediante un evento.

Para enviar un evento se utiliza la función emit.

Para que el elemento padre reciba el evento tenemos que usar la directiva v-on en el elemento hijo y asignarle la función que estará en el elemento padre.

Una ventaja de utilizar componentes es que lo podemos repetir a lo largo de la aplicación de forma fácil usando la etiqueta en el HTML que lo necesitemos. Cada componente es independiente de los otros.

👌

Compañeros sabios, vengo de js puro y siempre he considerado poner eventos en las etiquetas como una mala practica, por ejemplo esto ==>

<template>
  <img alt="Vue logo" src="./assets/logo.png">
  <HelloWorld msg="Welcome to Your Vue.js App"/>
</template>

pasar el parametro msg a el TAG ‘HelloWorld’ ¿esta bien? o ¿cual seria una buena practica?

Hola Devs:
-Muy importante concepto:
"El padre siempre se comunicara con el hijo mediante propiedades y el hijo mediante eventos