Skip to content
← Todas las preguntas
⚡ Intermedio

¿Qué son los componentes dinámicos y cómo funciona KeepAlive?

🧩 Componentes⚡ Rendimiento🎰 Slots⏳ Suspense🌀 Teleport

Los componentes dinámicos permiten cambiar entre componentes en tiempo de ejecución usando el elemento integrado <component> con la prop :is. Por defecto, Vue destruye el componente antiguo y crea uno nuevo en cada cambio. <KeepAlive> altera ese comportamiento almacenando las instancias en memoria.

Diagrama comparativo: sin KeepAlive los componentes se destruyen al cambiar, con KeepAlive se mantienen en caché

Componentes dinámicos

vue
<script setup>
import { ref, shallowRef } from 'vue'
import TabHome from './TabHome.vue'
import TabSettings from './TabSettings.vue'
import TabProfile from './TabProfile.vue'

const tabs = { TabHome, TabSettings, TabProfile }
const currentTab = shallowRef(TabHome)
</script>

<template>
  <button v-for="(comp, name) in tabs" :key="name" @click="currentTab = comp">
    {{ name }}
  </button>

  <!-- Se destruye y recrea en cada cambio -->
  <component :is="currentTab" />
</template>
Open in Vue Playground

Sin KeepAlive, cualquier estado local en TabSettings (inputs de formulario, posición de scroll, secciones expandidas) se reinicia cada vez que cambias de pestaña y vuelves.

Añadir KeepAlive

Envuelve <component> en <KeepAlive> para almacenar las instancias en caché en lugar de destruirlas.

vue
<template>
  <KeepAlive>
    <component :is="currentTab" />
  </KeepAlive>
</template>
Open in Vue Playground

Ahora cambiar de pestaña conserva el estado completo de cada componente.

Controlar qué se almacena en caché

Usa include, exclude y max para limitar el almacenamiento en caché.

vue
<template>
  <!-- Solo almacenar estos dos en caché -->
  <KeepAlive include="TabHome,TabSettings">
    <component :is="currentTab" />
  </KeepAlive>

  <!-- Almacenar todo excepto este -->
  <KeepAlive exclude="TabProfile">
    <component :is="currentTab" />
  </KeepAlive>

  <!-- Almacenar en caché como máximo 5 instancias (expulsión LRU) -->
  <KeepAlive :max="5">
    <component :is="currentTab" />
  </KeepAlive>
</template>
Open in Vue Playground

include y exclude comparan con el name del componente. Establécelo explícitamente con defineOptions:

vue
<script setup>
defineOptions({ name: 'TabSettings' })
</script>
Open in Vue Playground

Lifecycle hooks para componentes en caché

Los componentes en caché no disparan onMounted/onUnmounted al cambiar. Usa onActivated y onDeactivated en su lugar.

vue
<script setup>
import { onActivated, onDeactivated } from 'vue'

onActivated(() => {
  // El componente volvió a ser visible, refresca datos si es necesario
  refreshData()
})

onDeactivated(() => {
  // Componente oculto pero aún vivo, pausa el trabajo en segundo plano
  pausePolling()
})
</script>
Open in Vue Playground

Ciclo de vida completo de un componente en caché:

onMounted → onActivated → (el usuario cambia de pestaña) → onDeactivated
         → (el usuario vuelve) → onActivated → ...
         → (caché expulsado o padre destruido) → onUnmounted

KeepAlive con Vue Router

vue
<template>
  <router-view v-slot="{ Component, route }">
    <KeepAlive>
      <component :is="Component" :key="route.fullPath" />
    </KeepAlive>
  </router-view>
</template>
Open in Vue Playground

Usar route.fullPath como key significa que /users/1 y /users/2 se almacenan en caché por separado.

Cuándo NO usar KeepAlive

EscenarioPor qué
Componentes con mucha memoria (mapas, tablas grandes)Las instancias en caché permanecen en memoria
Datos sensibles (formularios de autenticación, flujos de pago)Los datos deben limpiarse al salir
Componentes con temporizadores en segundo plano que no puedes pausarSiguen ejecutándose mientras están ocultos
Páginas donde los usuarios esperan resultados frescosLos datos en caché desactualizados confunden a los usuarios

Ver también: ¿Qué son los componentes asíncronos? · ¿Qué son Teleport, Fragments y Suspense? · ¿Cómo funciona el atributo is?

Referencias

Publicado bajo la licencia MIT.