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.