image

Access unlimited bootcamps and 650+ courses forever

70
%OFF
Article image
Helton Silva
Helton Silva04/05/2026 15:20
Share

Vue 3 com uso do Keep alive

    Recentemente, me deparei com um problema frustrante em um cenário muito específico de navegação por abas. A tela possuía duas abas principais: uma de Dúvidas (FAQ) e outra com um Formulário.

    O gargalo acontecia durante o preenchimento: se o usuário estivesse no meio do formulário, tivesse uma dúvida e clicasse na aba de Dúvidas para ler algo, ao retornar para a aba do Formulário, todos os dados digitados haviam desaparecido. O componente era destruído e recriado do zero.

    A Solução Inicial (e trabalhosa):

    Minha primeira intuição foi recorrer a uma abordagem clássica: salvar os dados momentaneamente no localStorage a cada alteração e, ao final do envio do formulário, limpar essa chave. Embora funcione, é uma solução que exige muito código manual e gerenciamento de estado externo.

    A Solução Elegante com Vue:

    Buscando uma alternativa mais limpa, lembrei-me do . No Vue, ele é um componente embutido (built-in) e abstrato, o que significa que ele não renderiza nenhum elemento HTML real como uma tag div. Ele atua apenas como um "gerente invisível" no Virtual DOM, instruindo o Vue a fazer o cache do componente em vez de destruí-lo ao trocar de aba. Assim, o formulário e suas informações permanecem intactos na memória, melhorando a experiência do usuário com pouquíssimo esforço.

    1º Página que recebe as abas

    <script setup lang="ts">
    import { shallowRef } from "vue";
    import AbaFormulario from "../components/AbaFormulario.vue";
    import AbaDuvidas from "../components/AbaDuvidas.vue";
    
    const abaAtual = shallowRef(AbaFormulario);
    </script>
    
    <template>
    <div class="container-abas">
      <nav class="botoes-abas">
        <button
          :class="{ ativo: abaAtual === AbaFormulario }"
          @click="abaAtual = AbaFormulario"
        >
          Preencher Formulário
        </button>
    
        <button
          :class="{ ativo: abaAtual === AbaDuvidas }"
          @click="abaAtual = AbaDuvidas"
        >
          Dúvidas Frequentes
        </button>
      </nav>
    
      <div class="conteudo-aba">
        <KeepAlive>
          <component :is="abaAtual" />
        </KeepAlive>
      </div>
    </div>
    </template>
    
    <style scoped>
    .ativo {
    font-weight: bold;
    background-color: #e0e0e0;
    color: var(--black);
    }
    
    .botoes-abas {
    display: flex;
    gap: 10px;
    margin-bottom: 20px;
    }
    </style>
    

    O KeepAlive ele envolve o componentes dinâmico, no exemplo uso abas, mas poderia ser páginas também, pode ser qualquer arquivo .vue

    2º Componente de AbaFormulario

    <script setup lang="ts">
    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>Preencha seus dados</h2>
      <p>Comece a digitar, troque de aba e volte. Seus dados estarão aqui!</p>
    
      <form @submit.prevent>
        <div class="campo">
          <label>Nome:</label>
          <input
            v-model="formData.nome"
            type="text"
            placeholder="Digite seu nome"
          />
        </div>
    
        <div class="campo">
          <label>E-mail:</label>
          <input
            v-model="formData.email"
            type="email"
            placeholder="Digite seu e-mail"
          />
        </div>
    
        <div class="campo">
          <label>Mensagem:</label>
          <textarea
            v-model="formData.mensagem"
            rows="4"
            placeholder="Sua dúvida ou solicitação..."
          ></textarea>
        </div>
    
        <button type="button">Enviar</button>
      </form>
    </div>
    </template>
    
    <style scoped>
    .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;
    }
    </style>
    

    Veja que usamos o console.log para ver os gatilhos do ciclo.

    onActivated()

    Regista uma função de resposta a ser chamada depois da instância do componente for inserida no DOM como parte duma árvore armazenada para consulta imediata pelo .

    onDeactivated()​

    Regista uma função de resposta a ser chamada depois da instância do componente ser removida do DOM como parte duma árvore armazenada para consulta imediata pelo .

    3º Componente de AbaDuvidas

    <script setup lang="ts"></script>
    
    <template>
    <div class="duvidas-container">
      <h2>Dúvidas Frequentes (FAQ)</h2>
      <p>Aqui estão as respostas para as perguntas mais comuns.</p>
    
      <div class="faq-item">
        <h3>Preciso preencher todos os campos do formulário?</h3>
        <p>
          Sim, todos os campos são obrigatórios para que possamos entrar em
          contato de forma eficiente.
        </p>
      </div>
    
      <div class="faq-item">
        <h3>Qual o prazo de resposta?</h3>
        <p>Nossa equipe geralmente responde em até 24 horas úteis.</p>
      </div>
    </div>
    </template>
    
    <style scoped>
    .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;
    }
    </style>
    

    Cuidados com o keep alive

    Caso você precise carregar a página com reload, ele irá perde os dados, já que ele fica guardado nos componentes em memória (cache).

    Usamos o keep alive no lado do cliente, ótimo em aplicações SPA.

    Referência:

    https://pt.vuejs.org/guide/built-ins/keep-alive

    https://learnvue.co/articles/vue-keep-alive

    https://pt.vuejs.org/api/composition-api-lifecycle

    Share
    Recommended for you
    GFT - Fundamentos de Cloud com AWS
    Bootcamp Afya - Automação de Dados com IA
    Bootcamp NTT DATA: Backend Java com Spring AI
    Comments (0)