Renderizado condicional de slots

Aprender a renderizar slots en base a una condición con la Composition API de Vue 3


Si tu componente acepta slots, en ocasiones querrás comprobar si se han suministrado (o no). ¿Por qué?, por varias razones. Es posible que quieras añadir estilos específicos usando un div como wrapper y asegurarte que no lo renderizas si no hay contenido —slot— que mostrar, evitando un elemento HTML vacío.

De ahí lo de renderizado condicional.

Comprobar si existe contenido para un slot

Ahora bien. ¿cómo conseguirlo?. Con Options API es muy sencillo ya que todos los slots de un componente están disponibles en el objeto $slots. Si tu componente tiene al menos un slot, estará disponible bajo $slots.default. Si tiene más de un slot, invocando $slots obtendrás un array de VNodes usando sus nombres como key.

Teniendo esto claro, podemos comprobar si existe contenido para un slot y decidir qué hacer.

HTML
<!-- MyComponent.vue instantiation-->
<MyComponent>
  <p>Slot content</p>
</MyComponent>

    
JS
<!-- MyComponent.vue -->
<template>
  <div>
    <h1>Slots FTW 🔥</h1>
        <div v-if="$slots.default" class="">
            <slot />
        </div>
    <slot name="one" />
    <slot name="two" />
  </div>
</template>

    

Caso práctico con la Composition API

Hace poco me encontré con un escenario donde quería utilizar un componente de forma recursiva. La diferencia entre implementaciones es que en algunos casos se le pasará contenido a su slot y en otros no.

Por simplicidad he creado una pequeña demo donde tenemos un componente llamado TableRow.vue que acepta un slot. Dentro del componente, podemos acceder a la lista de slots con el helper useSlots y, con una propiedad computada, decidir si renderizar su contenido o no.

JS
import { useSlots, computed } from 'vue';

const slots = useSlots();

const hasExtraContent = computed(() => !!slots.extra);

    

Si es la primera vez que ves el operador !! (en realidad no es un operador es el operador ! dos veces) doble exclamación no te preocupes, el primer ! convierte el valor en la versión booleana contraria, mientras que el segundo ! invierte el valor booleano. Es una manera ***moderna******* de convertir un objeto en su Boolean equivalente. Boolean() realiza la misma acción.

Ahora podemos usar hasExtraContent para comprobar si el slot extra tiene contenido.

HTML
<template>
  <div class="file">
    ...
    <div v-if="hasExtraContent">
      <slot name="extra" />
    </div>
    ...
  </div>
</template>

    

Demo

Juan Andrés Núñez
Juan Andrés Núñez
Ingeniero Frontend Senior. Especialista en Vue.js. Speaker. Docente profesional. Estoico.