Todos los artículos

Guía práctica de Vue 3: Cómo usar <Teleport> para modales, tooltips y notificaciones adaptativas

¿Sabías que puedes mover parte del DOM de un componente Vue a otro lugar del HTML sin romper la reactividad? En esta guía aprenderás cómo usar <Teleport> en Vue 3, desde lo básico hasta casos reales como notificaciones, menús contextuales y overlays.

LA

Luis Aldair Quispe Rios

2 min de lectura
Guía práctica de Vue 3: Cómo usar <Teleport> para modales, tooltips y notificaciones adaptativas

¿Qué es <Teleport>?

<Teleport> es un componente integrado de Vue 3 que te permite renderizar una parte del DOM de tu componente en otro lugar del documento HTML, sin romper la lógica del componente ni su reactividad.

Imagina que tienes un modal, una notificación, o un menú que visualmente necesita estar en el <body> o en un contenedor global, pero lógicamente pertenece a un componente específico. Aquí es donde entra <Teleport>.

¿Cómo usar <Teleport>? – La forma básica

La estructura es muy simple:

<script setup lang="ts"></script>

<template>
  <Teleport to="body">
    <!-- contenido que será movido al <body> -->
  </Teleport>
</template>
  • El prop to acepta un selector CSS o un nodo del DOM.

  • Todo lo que esté dentro del <Teleport> se renderiza en ese destino.

  • Se mantiene el contexto del componente padre: props, eventos e inyección siguen funcionando igual.

Casos de uso prácticos

Notificaciones globales

Estructura base:

<!-- index.html -->
<div id="app"></div>
<div id="notifications"></div>

Componente NotificationManager.vue

<script setup lang="ts">
import { ref } from 'vue'
const notes = ref([])

function addNotification(text) {
  notes.value.push({ id: Date.now(), text })
  setTimeout(() => notes.value.shift(), 3000)
}

defineExpose({ addNotification }) // permite usarlo desde refs
</script>

<template>
  <Teleport to="#notifications">
    <div v-for="n in notes" class="note">{{ n }}</div>
  </Teleport>
</template>

Uso en otro componente:

<script setup lang="ts">
import { useTemplateRef } from 'vue'
import NotificationManager from './NotificationManager.vue'

const notifRef = useTemplateRef('notifRef')

function handleAction() {
  notifRef.value?.addNotification('¡Acción exitosa!')
}
</script>

<template>
  <NotificationManager ref="notifRef" />
  <button @click="handleAction">Guardar</button>
</template>

Comportamiento adaptativo con disabled:

Puedes condicionar el teleport para ciertos dispositivos (ej. overlay en desktop, inline en mobile):

<script setup lang="ts">
import { useMediaQuery } from '@vueuse/core'

// Define isMobile usando media query reactiva
const isMobile = useMediaQuery('(max-width: 768px)')
</script>

<template>
 <Teleport :disabled="isMobile" to="body">
   <div class="tooltip">Ayuda</div>
 </Teleport>
</template>

¿Cómo funciona?:

  • useMediaQuery('(max-width: 768px)') retorna un ref<boolean> reactivo que se actualiza automáticamente cuando cambia el tamaño de la pantalla

  • Si isMobile.value === true (pantallas menores a 768px), <Teleport> se desactiva y el tooltip se muestra inline en el flujo del componente.

  • Si isMobile.value === false, el tooltip se teletransporta al <body>, ideal para overlays en escritorio.

  • <Teleport> se adapta automáticamente sin recarga ni lógica adicional.

Consideraciones importantes

  • El destino (to) debe existir en el DOM cuando el <Teleport> se monta.

  • Si el destino no está disponible aún, usa defer.

  • No afecta el árbol de componentes en Vue: los componentes teletransportados siguen siendo hijos del componente que los contiene.

Extra: Transiciones animadas

Puedes usar <Transition> dentro del <Teleport> para animaciones fluidas.

<script setup lang="ts">

</script>

<template>
 <Teleport to="body">
   <Transition name="fade">
     <div class="modal">...</div>
   </Transition>
 </Teleport>
</template>

Conclusión

<Teleport> es una herramienta poderosa para separar la lógica de tus componentes del posicionamiento en el DOM. Con to, disabled y defer, puedes adaptarlo a múltiples escenarios, desde modales simples hasta comportamientos complejos y contextuales.

Sigue leyendo

¿Cómo integrar Tailwind 4 en Vue.js 3 + Vite?

¿Cómo integrar Tailwind 4 en Vue.js 3 + Vite?

Tailwind CSS 4 ha llegado con una arquitectura optimizada para rendimiento y flexibilidad, ofreciendo compilaciones hasta 5 veces más rápidas y un flujo de trabajo más ágil. En este post, exploraremos cómo integrar esta nueva versión con Vue 3, aprovechando características como la detección automática de contenido, el nuevo motor de alto rendimiento, las variables CSS nativas y la compatibilidad con Vite. Si quieres construir interfaces modernas con menos configuración y más poder, acompáñame en esta guía donde aprenderás a instalar, configurar y usar Tailwind CSS 4 en Vue 3. 🚀
¿Y si Vue.js también hablara Web Components? La magia de defineCustomElement

¿Y si Vue.js también hablara Web Components? La magia de defineCustomElement

Si eres fan de Vue.js como yo, seguramente has creado componentes reutilizables una y otra vez. Pero… ¿alguna vez te preguntaste cómo compartir tus componentes Vue fuera de una app Vue? ¿Qué pasaría si pudieras usarlos en React, Angular o incluso en HTML puro? La respuesta está en los Web Components y Vue tiene una herramienta poderosa para eso: defineCustomElement. Hoy te voy a contar cómo Vue y los Web Components pueden ser mejores amigos. Te prometo que al final vas a querer probarlo en tu próximo proyecto (o experimento).
¿Cómo usar defineExpose?

¿Cómo usar defineExpose?

Dentro de un componente que utiliza <script setup>, defineExpose() es una macro del compilador que permite exponer de forma explícita variables, funciones o incluso refs para que puedan ser accesibles desde el exterior. Esto es útil, por ejemplo, cuando queremos controlar un componente a través de una referencia (ref) en el componente padre.