Eventos en Vue: comunicar hijo a padre

Clase 28 de 53Curso Profesional de Vue.js 2

Resumen

Domina la comunicación entre componentes en Vue.js con eventos claros, payloads precisos y estilos encapsulados. Aquí verás cómo un hijo notifica al padre con $emit, cómo el padre escucha con v-on/@, y cómo resaltar la selección con v-bind:class y CSS scoped para evitar efectos colaterales.

¿Cómo enviar datos del hijo al padre en Vue.js?

La clave es usar eventos. De padre a hijo usamos props (inmutables), pero del hijo al padre enviamos información con $emit. Al hacer clic en el botón de reproducción, el componente hijo emite un evento con el ID de la canción como payload para que el padre lo escuche y actualice su estado.

¿Qué hace $emit y cómo pasar el payload?

  • Emite un evento con un nombre claro: por ejemplo, "select".
  • Adjunta un payload: aquí, el ID de la canción.
  • Se usa desde un método del hijo.
<!-- Hijo: pm-track.vue --> <template> <button @click="selectTrack">Play</button> </template> <script> export default { methods: { selectTrack() { // Enviar al padre el ID de la canción como payload. this.$emit('select', /* id de la canción */) } } } </script>

¿Cómo escucha el padre con v-on o @?

  • Usa la directiva v-on (o @) con el mismo nombre del evento.
  • Define un método que reciba el payload y actualice data.
  • Guarda el ID en una variable como selectedTrack.
<!-- Padre: app.vue (uso del componente) --> <pm-track @select="setSelectedTrack" /> <script> export default { data() { return { selectedTrack: '' } }, methods: { setSelectedTrack(id) { this.selectedTrack = id } } } </script>
  • Consejo: en las herramientas de desarrollo verás el evento emitido con su payload y el emisor.

¿Cómo evitar errores comunes al asignar data?

  • No asignes el nombre del método en vez de la propiedad: evita escribir algo como this.setSelectedTrack = id.
  • La asignación correcta es: this.selectedTrack = id.
  • Verifica en la pestaña de componentes que selectedTrack reciba el ID esperado.

¿Cómo resaltar el elemento seleccionado con v-bind:class?

Para destacar la canción activa, aplica una clase condicional cuando el ID del ítem coincida con selectedTrack. Así, solo un elemento tendrá la clase activa a la vez.

¿Qué sintaxis de objeto usar en :class?

  • Usa la forma objeto en :class: { 'is-active': condicion }.
  • La condición compara t.id === selectedTrack.
  • Se escribe en el componente donde tengas acceso a ambos valores.
<!-- Uso del componente en el padre con clase condicional --> <pm-track :class="{ 'is-active': t.id === selectedTrack }" />
/* Estilo para resaltar el elemento activo */ .is-active { border: 3px solid; /* verde */ }
  • Alternativas de :class: cadena simple, operador ternario o forma objeto.
  • Recuerda las comillas: si fuera hay dobles, dentro usa simples.

¿Cómo aislar estilos con scoped y limpiar el CSS global?

Un CSS global puede afectar componentes no deseados. Si en loader definiste .content { min-height: 40vh; }, esa regla impactará todas las clases .content del proyecto. Encapsula estilos por componente para evitarlo.

¿Por qué min-height en loader afectaba otros componentes?

  • El alcance global de CSS aplica por cascada.
  • .content en loader terminó deformando cajas de canciones.
  • Inspecciona y verás .content heredando min-height y padding fuera de loader.

¿Cómo solucionarlo con scoped?

  • Agrega el atributo scoped al bloque de estilos del componente afectado.
  • Eso limita el alcance del CSS al componente actual.
<!-- loader.vue --> <style scoped> .content { min-height: 40vh; /* padding existente, si aplica */ } </style>
  • Tras compilar, los estilos dejarán de afectar otros componentes como los tracks.

¿Qué otros ajustes rápidos mejoran el look?

  • Elimina la clase "hash shadow" del navbar si no se usa, para quitar la sombra.
  • Verifica con el inspector que la clase is-active se mueva al cambiar de selección.

¿Tienes dudas sobre eventos, payloads o estilos scoped en Vue.js? Cuéntame tu caso en los comentarios y lo vemos juntos.