Vue 3 KeepAlive: Routen-Cache, Zustandserhalt und Speicherkontrolle

前端工程(Aktualisiert am 15. Juli 2026)

<KeepAlive> ist Vue's eingebaute Komponente zum Cachen inaktiver Component-Instanzen. Sie ist nützlich, wenn ein Nutzer eine Seite verlässt und später zurückkehrt, ohne Filter, Formularzustand, Scrollposition oder lokale UI-Zustände zu verlieren.

KeepAlive lässt sich aber leicht falsch einsetzen. Wenn jede Route gecacht wird, wächst der Speicher. Wenn alte Daten nie aktualisiert werden, sehen Nutzer veraltete Informationen. Wenn Component-Namen und Route-Keys nicht kontrolliert sind, verhält sich der Cache anders als erwartet.

Referenzen:

Wann KeepAlive sinnvoll ist

Nutze KeepAlive für Seiten, bei denen lokaler Zustand den Workflow verbessert:

  • Listen mit Filtern, Suche, Tabs und Scrollposition.
  • Mehrstufige Formulare, bei denen Nutzer kurz eine andere Seite prüfen.
  • Dashboards mit teurem lokalen Rendering.
  • Admin-Tabs, die beim Wechsel nicht zurückgesetzt werden sollen.

Vermeide KeepAlive, wenn:

  • Die Seite günstig neu erstellt werden kann.
  • Die Seite immer frische Daten zeigen muss.
  • Die Seite sensible Daten enthält, die beim Verlassen verschwinden sollen.
  • Die Komponente Timer, Subscriptions oder große Objekte hält, die schwer zu pausieren sind.

Die Standardeinstellung sollte selektives Caching sein, nicht das Cachen jeder Route.

Basis-Setup für Routen

Vue Router stellt die gerenderte Route über den RouterView-Slot bereit. Dort lässt sich KeepAlive sauber einbauen.

<!-- App.vue -->
<template>
  <RouterView v-slot="{ Component, route }">
    <KeepAlive :include="cachedComponentNames" :max="8">
      <component
        v-if="route.meta.keepAlive"
        :is="Component"
        :key="route.meta.cacheKey || route.name"
      />
    </KeepAlive>

    <component
      v-if="!route.meta.keepAlive"
      :is="Component"
      :key="route.fullPath"
    />
  </RouterView>
</template>

<script setup lang="ts">
const cachedComponentNames = ["UserList", "OrderList", "ReportDashboard"]
</script>

Route-Metadaten halten die Entscheidung nahe an der Routendefinition.

// router.ts
import type { RouteRecordRaw } from "vue-router"

export const routes: RouteRecordRaw[] = [
  {
    path: "/users",
    name: "Users",
    component: () => import("./views/UserList.vue"),
    meta: {
      keepAlive: true,
      cacheKey: "users-list"
    }
  },
  {
    path: "/users/:id",
    name: "UserDetail",
    component: () => import("./views/UserDetail.vue"),
    meta: {
      keepAlive: false
    }
  }
]

Halte Component-Namen stabil, wenn du include oder exclude nutzt, da Vue nach Namen matcht.

<!-- UserList.vue -->
<script setup lang="ts">
defineOptions({
  name: "UserList"
})
</script>

Daten aktualisieren, ohne UI-Zustand zu verlieren

Der häufigste Fehler sind veraltete Daten. Eine gecachte Seite kann alte API-Ergebnisse behalten, nachdem der Nutzer zurückkehrt.

Nutze onActivated, um zu prüfen, ob Daten aktualisiert werden sollen. Lade nicht blind bei jeder Aktivierung neu, sonst verlierst du einen Teil des Cache-Nutzens.

<script setup lang="ts">
import { onActivated, onDeactivated, ref } from "vue"

const users = ref<User[]>([])
const loading = ref(false)
const lastLoadedAt = ref(0)
const STALE_AFTER_MS = 60_000

async function loadUsers() {
  loading.value = true
  try {
    users.value = await fetchUsers()
    lastLoadedAt.value = Date.now()
  } finally {
    loading.value = false
  }
}

onActivated(() => {
  const isStale = Date.now() - lastLoadedAt.value > STALE_AFTER_MS
  if (!users.value.length || isStale) {
    void loadUsers()
  }
})

onDeactivated(() => {
  // Pause work that should not continue while the page is hidden.
})
</script>

So bleibt lokaler UI-Zustand erhalten, während alte Daten bei Bedarf aktualisiert werden.

Scrollposition erhalten

KeepAlive erhält die Component-Instanz, aber Scrollverhalten kann trotzdem durch Layout, Transitions oder Scrollcontainer beeinflusst werden.

Für einen scrollbaren Container kannst du die Position speichern und wiederherstellen:

<template>
  <main ref="scrollEl" class="page-scroll">
    <!-- list content -->
  </main>
</template>

<script setup lang="ts">
import { nextTick, onActivated, onDeactivated, ref } from "vue"

const scrollEl = ref<HTMLElement | null>(null)
let savedTop = 0

onDeactivated(() => {
  savedTop = scrollEl.value?.scrollTop ?? 0
})

onActivated(async () => {
  await nextTick()
  if (scrollEl.value) {
    scrollEl.value.scrollTop = savedTop
  }
})
</script>

Teste direkte Navigation, Zurück-Button und programmgesteuerte Routenwechsel.

Cache-Größe begrenzen

max begrenzt, wie viele Component-Instanzen KeepAlive speichert. Wenn die Grenze überschritten wird, entfernt Vue ältere Cache-Einträge.

<KeepAlive :max="8">
  <component :is="Component" />
</KeepAlive>

Wähle den Wert nach echten Nutzer-Workflows. Kleine Admin-Apps brauchen oft nur wenige gecachte Listen. Setze den Wert nicht sehr hoch, nur um State-Management-Probleme zu verstecken.

Speicherlecks vermeiden

Gecachte Komponenten werden deaktiviert, nicht unmounted. Manche Aufräumarbeiten gehören daher in onDeactivated, finale Aufräumarbeiten weiterhin in onUnmounted.

Pausiere oder entferne:

  • Intervalle und Timeouts.
  • WebSocket- oder SSE-Listener, die im Hintergrund nicht laufen sollen.
  • ResizeObserver und IntersectionObserver.
  • Globale Event Listener.
  • Große temporäre Arrays, Maps oder Blobs.
import { onActivated, onDeactivated, onUnmounted } from "vue"

let timer: number | undefined

function startPolling() {
  timer = window.setInterval(refreshStatus, 15_000)
}

function stopPolling() {
  if (timer) {
    window.clearInterval(timer)
    timer = undefined
  }
}

onActivated(startPolling)
onDeactivated(stopPolling)
onUnmounted(stopPolling)

Wenn Speicher nach wiederholter Navigation weiter wächst, nutze Browser-Devtools statt zu raten.

Cache-Keys und dynamische Routen

Dynamische Routen brauchen bewusste Keys. Wenn Detailseiten denselben Component-Namen und denselben Key nutzen, teilen sie eventuell eine Cache-Instanz.

<!-- Share one cached instance for the user list -->
<component :is="Component" :key="route.name" />

<!-- Separate cache entry for each route parameter -->
<component :is="Component" :key="route.fullPath" />

<!-- Controlled custom key -->
<component :is="Component" :key="route.meta.cacheKey || route.fullPath" />

Nutze fullPath nicht leichtfertig für Listen mit vielen Query-Kombinationen. Das kann zu viele Cache-Einträge erzeugen.

Praktische Regeln

Nutze KeepAlive für wertvollen lokalen Zustand, nicht als allgemeinen Performance-Schalter.

Gute Kandidaten:

  • Suchergebnislisten.
  • Formularentwürfe.
  • Dashboards mit teurem Chart-Setup.
  • Tabs, die sofort zurückkehren sollen.

Schlechte Kandidaten:

  • Login- und Auth-Seiten.
  • Zahlungs- oder sicherheitssensible Seiten.
  • Seiten, die jedes Mal neu laden müssen.
  • Detailseiten mit vielen IDs ohne klare Grenze.

Abschluss-Checkliste

Vor dem Release prüfen:

  • Nur ausgewählte Routen nutzen KeepAlive.
  • Gecachte Components haben stabile Namen.
  • Dynamische Routen haben bewusste Keys.
  • max ist sinnvoll gesetzt.
  • Daten werden bei Bedarf über onActivated aktualisiert.
  • Timer, Observer und Listener pausieren bei Deaktivierung.
  • Sensible Seiten werden nicht gecacht.
  • Zurück-Button, direkte Navigation und Tabwechsel sind getestet.

KeepAlive ist zuverlässig, wenn es als Zustandserhalt behandelt wird, nicht als automatische Performance-Magie.

Probiere diese browser-lokalen Tools aus — keine Registrierung erforderlich →

#Vue3 KeepAlive#组件缓存#路由缓存#性能优化#include exclude#responsive component caching#layout template cache#2026#前端工程