Vue 3 与 Keep-alive

发布: (2026年3月12日 GMT+8 19:32)
5 分钟阅读
原文: Dev.to

Source: Dev.to

问题

在一个有两个标签页的界面 – 疑问(FAQ)表单 – 用户在切换标签页时会失去在表单中输入的所有内容。表单组件被销毁并重新创建,导致状态丢失。

初始解决方案(繁琐)

在每次对 localStorage 进行更改时保存数据,并在提交表单时清除键。可行,但需要大量手动代码和外部状态管理。

优雅的 Vue 解决方案

Vue 拥有 <keep-alive> 组件(内置且抽象)。它不会生成任何真实的 HTML 元素;只会指示 Vue 缓存 组件,而不是在切换标签页时销毁它。这样,表单及其数据就会以极少的开销保留在内存中。

1️⃣ 接收标签页的页面

import { shallowRef } from "vue";
import AbaFormulario from "../components/AbaFormulario.vue";
import AbaDuvidas from "../components/AbaDuvidas.vue";

const abaAtual = shallowRef(AbaFormulario);
<div class="botoes-abas">
  <button @click="abaAtual = AbaFormulario" :class="{ ativo: abaAtual === AbaFormulario }">
    Preencher Formulário
  </button>
  <button @click="abaAtual = AbaDuvidas" :class="{ ativo: abaAtual === AbaDuvidas }">
    Dúvidas Frequentes
  </button>
</div>

<keep-alive>
  <component :is="abaAtual" />
</keep-alive>
.ativo {
  font-weight: bold;
  background-color: #e0e0e0;
  color: var(--black);
}

.botoes-abas {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
}

<keep-alive> 包裹动态组件。在示例中我们使用标签页,但它可以是任何 .vue 组件(甚至是页面)。

2️⃣ 组件 AbaFormulario

<script setup>
import { ref, onActivated, onDeactivated } from "vue";

const formData = ref({
  nome: "",
  email: "",
  mensagem: "",
});

onActivated(() => {
  console.log("Formulário ATIVADO (Recuperado do cache)");
});

onDeactivated(() => {
  console.log("Formulário DESATIVADO (Guardado no cache)");
});
</script>

<template>
  <div class="formulario-container">
    <h2>填写您的信息</h2>
    <p>开始输入,切换标签页后再返回。您的数据将会保留在这里!</p>

    <div class="campo">
      <label>姓名:</label>
      <input v-model="formData.nome" type="text" />
    </div>

    <div class="campo">
      <label>电子邮件:</label>
      <input v-model="formData.email" type="email" />
    </div>

    <div class="campo">
      <label>留言:</label>
      <textarea v-model="formData.mensagem"></textarea>
    </div>

    <button>发送</button>
  </div>
</template>
.formulario-container {
  padding: 20px;
  border: 1px solid #ccc;
  border-radius: 8px;
}

.campo {
  margin-bottom: 15px;
  display: flex;
  flex-direction: column;
}

input,
textarea {
  padding: 8px;
  margin-top: 5px;
  border: 1px solid #999;
  border-radius: 4px;
}

button {
  padding: 10px 15px;
  background-color: #4caf50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

使用 <keep-alive> 的生命周期

钩子触发时机
onActivated当组件实例从缓存插入到 DOM 后。
onDeactivated当组件实例从 DOM 中移除并存入缓存后。
<template>
  <div class="duvidas-container">
    <h2>常见问题 (FAQ)</h2>
    <p>这里是对最常见问题的回答。</p>

    <div class="faq-item">
      <h3>我需要填写表单的所有字段吗?</h3>
      <p>是的,所有字段都是必填的,以便我们能够高效地联系您。</p>
    </div>

    <div class="faq-item">
      <h3>响应时间是多久?</h3>
      <p>我们的团队通常在最多 24 个工作小时内回复。</p>
    </div>
  </div>
</template>
.duvidas-container {
  padding: 20px;
  border: 1px solid #ccc;
  border-radius: 8px;
  background-color: var(--black);
}

.faq-item {
  margin-top: 15px;
  padding-bottom: 10px;
  border-bottom: 1px dashed #ccc;
}

h3 {
  margin-bottom: 5px;
  color: var(--white);
  font-size: 1.1em;
}

结论

使用 <keep-alive>onActivated / onDeactivated 钩子,我们能够 保留表单状态 在切换标签页时,无需 localStorage 或外部状态管理。实现简短、清晰,显著提升用户体验。

退出全屏模式

关于 keep-alive 的注意事项

如果您需要使用 reload 重新加载页面,它将丢失数据,因为这些数据保存在内存中的组件(缓存)里。

我们在客户端使用 keep-alive —— 对 SPA 应用非常有用。

参考

  • (未列出任何项目)
0 浏览
Back to Blog

相关文章

阅读更多 »