Slots: HTML dinámico en componentes Vue

Clase 29 de 53Curso Profesional de Vue.js 2

Resumen

Los slots son una forma clara y flexible de inyectar HTML dinámico desde el componente padre hacia el hijo, evitando sobrecargar con propiedades y lógica. Aquí verás cómo crear slots con nombre, cómo el contenido del padre tiene precedencia y cómo aplicarlo en una notificación que se muestra solo cuando no hay resultados en la API y se cierra automáticamente con watchers y setTimeout de JavaScript.

¿Qué es un slot y para qué sirve?

Un slot permite que un componente hijo defina áreas “vacías” que el padre puede rellenar con su propio HTML. Si el padre no provee contenido, el hijo puede mostrar un contenido por defecto. Esto es útil para títulos y cuerpos personalizados, y para componentes como modales con botones y textos variables.

¿Cómo se define un slot con nombre?

En el hijo se declaran slots con nombre para secciones específicas como “title” y “body”. Si el padre no los rellena, se muestran valores por defecto.

<!-- child-component -->
<div class="container">
  <slot name="title">
    <h1>Título por defecto</h1>
  </slot>

  <slot name="body">
    <p>Cuerpo por defecto.</p>
  </slot>
</div>

¿Cómo lo reemplaza el componente padre?

El padre inyecta HTML usando el atributo slot con el nombre correspondiente. El contenido del padre tiene precedencia sobre el del hijo.

<!-- app.view -->
<child-component>
  <h1 slot="title">título desde el padre</h1>
  <div slot="body">
    <p>Lorem ipsum.</p>
    <p>Otro párrafo.</p>
  </div>
</child-component>

¿Cómo aplicar slots en una notificación con Bulma?

Se crea un componente de notificación con estructura Bulma, un slot “body” con texto por defecto y estilos en SCSS con alcance limitado.

<!-- share/notification.view -->
<div class="container">
  <div class="columns">
    <div class="column is-5 is-offset-4">
      <div class="notification is-danger">
        <slot name="body">algo anduvo mal.</slot>
      </div>
    </div>
  </div>
</div>

<style lang="scss" scoped>
.notification {
  margin: 10px;
}
</style>

Para usarlo e inyectar el mensaje desde el padre:

<!-- app.view -->
<pm-notification v-show="showNotification">
  <p slot="body">no se encontraron resultados.</p>
</pm-notification>

¿Cómo mostrarlo solo cuando no hay resultados en la API?

Se define un booleano en data y se actualiza tras la búsqueda. Se usa comparación estricta en JavaScript.

// app.view
export default {
  data() {
    return { showNotification: false };
  },
  methods: {
    async search() {
      const res = await this.fetchTracks();
      // total de resultados en res.tracks.total
      this.showNotification = res.tracks.total === 0; // estricto: ===
    }
  }
};
  • Variable booleana: showNotification en false al iniciar.
  • Visibilidad con directiva: v-show en el componente de notificación.
  • Decisión por datos: res.tracks.total === 0.

¿Cómo cerrarlo automáticamente con un watcher y setTimeout?

Un watcher observa showNotification y, si es true, programa su ocultamiento a los 3 segundos.

// app.view
export default {
  watch: {
    showNotification(val) {
      if (!val) return; // evita bucles innecesarios
      setTimeout(() => {
        this.showNotification = false;
      }, 3000);
    }
  }
};
  • Lógica reactiva: el watcher se llama igual que la propiedad observada.
  • Temporización: setTimeout con 3000 milisegundos.
  • Prevención de loops: no actúa cuando es false.

¿Qué buenas prácticas y conceptos refuerza este patrón?

Los ejemplos consolidan habilidades esenciales para componentes reutilizables y mantenibles.

  • Slots con nombre: title y body para secciones claras.
  • Contenido por defecto: asegura mensajes útiles si el padre no define HTML.
  • Precedencia del padre: reemplaza el contenido del hijo cuando hay slot.
  • Estructura con Bulma: container, columns, column, notification, is-danger.
  • Estilos con SCSS y scope: evita afectar otros componentes.
  • Comparación estricta en JavaScript: uso de === para evaluar resultados de la API.
  • Funciones flecha: arrow functions en callbacks concisos.
  • Temporización con setTimeout: cierre automático tras 3 segundos.
  • Reactividad con watchers: nombre idéntico a la propiedad observada.
  • Importaciones con alias: uso de @ gracias a webpack para rutas claras.
  • Flexibilidad de HTML: slots admiten múltiples elementos, no solo un tag.
  • Uso típico: componentes como modales y notificaciones con títulos y cuerpos dinámicos.

¿Te gustaría ver variaciones de este patrón con diferentes estilos o reglas de negocio? Cuéntame qué caso necesitas resolver y lo armamos juntos.

      Slots: HTML dinámico en componentes Vue