Plugin Event Bus: comunicar componentes sin relación en Vue

Clase 30 de 53Curso Profesional de Vue.js 2

Resumen

Potencia tus interfaces en Vue con una estrategia clara para mostrar resultados de búsqueda, un plugin de event bus para comunicar componentes sin relación directa y un player de audio en HTML5. Aquí encontrarás los pasos esenciales, el código clave y las prácticas recomendadas para que todo funcione de forma consistente y mantenible.

¿Cómo mejorar el notification component para comunicar resultados?

Mostrar feedback inmediato eleva la experiencia de usuario. La propuesta es que el componente de notificación informe tanto errores como la cantidad de resultados hallados, y que aparezca siempre después de una búsqueda.

  • Agregar una propiedad para el color. Por ejemplo: verde cuando todo estuvo bien y rojo cuando hubo error. Puedes mapearlo a clases de Bulma como isDanger o isSucces.
  • Mostrar el mensaje siempre tras la búsqueda. No sólo cuando hay errores.
  • Hacer el contenido del mensaje condicional. Usar v-show o v-if para alternar entre “no se encontraron resultados” y “se encontraron N resultados”.

Ejemplo orientativo:

<notification :class="['notification', type]">
  <template v-if="hasError">No se encontraron resultados.</template>
  <template v-else>Se encontraron {{ total }} resultados.</template>
</notification>

Claves que refuerzas: propiedades de componente, renderizado condicional con v-show/v-if y uso de clases utilitarias de Bulma.

¿Cómo comunicar componentes no relacionados en Vue con un plugin Event Bus?

Cuando los componentes no son padre-hijo, Vue no trae una alternativa directa. La solución didáctica propuesta: crear un plugin que inyecte un event bus global usando una nueva instancia de Vue, accesible como this.$bus con la misma API de $emit y $on.

¿Cómo crear el plugin?

Estructura en src/plugins un archivo event-bus.js que exponga install y extienda el prototype de Vue:

// src/plugins/event-bus.js
const EventBus = {};

EventBus.install = function (Vue) {
  Vue.prototype.$bus = new Vue(); // misma API: $emit, $on.
};

export default EventBus;

Puntos clave: función install, extensión via Vue.prototype y convención del prefijo $ para indicar funcionalidad inyectada.

¿Cómo instalar y usarlo?

Regístralo en main.js con Vue.use para que esté disponible en todos los componentes.

// main.js
import Vue from 'vue';
import EventBus from '@/plugins/event-bus';

Vue.use(EventBus);

Emitir desde cualquier componente (por ejemplo, en Track.vue al seleccionar una canción):

this.$bus.$emit('set-track', track);

Escuchar en otro componente no relacionado (por ejemplo, en Player.vue dentro del hook created):

created() {
  this.$bus.$on('set-track', (track) => {
    this.track = track;
  });
}

Beneficios inmediatos: desacoplamiento, comunicación entre hermanos o componentes en ramas distintas y reutilización simple. Además, se sugiere el uso de plugins para utilidades frecuentes como local storage (por ejemplo, this.$storage) sin imports repetidos.

¿Cómo integrar el player de audio y reproducir un track seleccionado?

Se crea un componente Player.vue que muestra portada, título, duración y un reproductor HTML5. El player escucha el evento set-track por el bus y actualiza su estado.

¿Qué estructura tiene Player.vue?

  • Template con imagen, título en strong, duración en small y etiqueta audio con controls.
  • data que expone track como objeto vacío.
  • Estilos con tamaño fijo y borde redondeado.

Ejemplo base:

<template>
  <div class="content">
    <p>
      <img class="image" :src="track.album && track.album.images ? track.album.images[0].url : ''" />
    </p>
    <p><strong>{{ track.name }}</strong></p>
    <p><small>[{{ track.duration_ms }} ms]</small></p>
    <p>
      <audio controls>
        <source :src="track.preview_url" />
      </audio>
    </p>
  </div>
</template>

<script>
export default {
  data() {
    return { track: {} };
  },
  created() {
    this.$bus.$on('set-track', (track) => { this.track = track; });
  }
};
</script>

<style scoped lang="scss">
.image { width: 124px; border-radius: 50%; }
</style>

Notas prácticas del flujo: - preview_url puede venir nulo en algunas canciones. Sólo se reproducirá cuando exista. - El reproductor HTML5 usa controls: cada navegador lo renderiza con su UI nativa. - La imagen proviene de track.album.images[0].url. El título desde track.name. La duración se muestra en milisegundos a modo informativo. - Mantener scoped en estilos para no afectar otras imágenes.

¿Cómo se integra en la interfaz?

  • Se importa y registra en el Header para renderizarlo bajo el título y subtítulo.
  • El componente Track emite al seleccionar una canción. Player escucha y actualiza su interfaz y el audio.
  • Uso de alias @ simplifica imports desde '@/components/Player'.

¿Te gustaría compartir más casos de uso para plugins en Vue o mejoras al player? Deja tus ideas y dudas en los comentarios.