<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Helton Carlos Brito Silva</title>
    <description>The latest articles on DEV Community by Helton Carlos Brito Silva (@heltonbrito).</description>
    <link>https://dev.to/heltonbrito</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1260302%2F2d107389-95ab-4387-8739-fa27d100ecaa.png</url>
      <title>DEV Community: Helton Carlos Brito Silva</title>
      <link>https://dev.to/heltonbrito</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/heltonbrito"/>
    <language>en</language>
    <item>
      <title>Vue 3 e Keep alive</title>
      <dc:creator>Helton Carlos Brito Silva</dc:creator>
      <pubDate>Thu, 12 Mar 2026 11:32:06 +0000</pubDate>
      <link>https://dev.to/heltonbrito/vue-3-e-keep-alive-4l9n</link>
      <guid>https://dev.to/heltonbrito/vue-3-e-keep-alive-4l9n</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Solução Inicial (e trabalhosa):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Solução Elegante com Vue:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1º Página que recebe as abas&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;shallowRef&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;AbaFormulario&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../components/AbaFormulario.vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;AbaDuvidas&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../components/AbaDuvidas.vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;abaAtual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;shallowRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AbaFormulario&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container-abas"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;nav&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"botoes-abas"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
        &lt;span class="na"&gt;:class=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;{ ativo: abaAtual === AbaFormulario }"
        @click="abaAtual = AbaFormulario"
      &amp;gt;
        Preencher Formulário
      &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
        &lt;span class="na"&gt;:class=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;{ ativo: abaAtual === AbaDuvidas }"
        @click="abaAtual = AbaDuvidas"
      &amp;gt;
        Dúvidas Frequentes
      &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"conteudo-aba"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;KeepAlive&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;:is=&lt;/span&gt;&lt;span class="s"&gt;"abaAtual"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/KeepAlive&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt; &lt;span class="na"&gt;scoped&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nc"&gt;.ativo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#e0e0e0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--black&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.botoes-abas&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;strong&gt;2º Componente de AbaFormulario&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onActivated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onDeactivated&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;mensagem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;onActivated&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Formulário ATIVADO (Recuperado do cache)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;onDeactivated&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Formulário DESATIVADO (Guardado no cache)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"formulario-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Preencha seus dados&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Comece a digitar, troque de aba e volte. Seus dados estarão aqui!&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;submit.prevent&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"campo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;Nome:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
          &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"formData.nome"&lt;/span&gt;
          &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
          &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Digite seu nome"&lt;/span&gt;
        &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"campo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;E-mail:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
          &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"formData.email"&lt;/span&gt;
          &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;
          &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Digite seu e-mail"&lt;/span&gt;
        &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"campo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;Mensagem:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt;
          &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"formData.mensagem"&lt;/span&gt;
          &lt;span class="na"&gt;rows=&lt;/span&gt;&lt;span class="s"&gt;"4"&lt;/span&gt;
          &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Sua dúvida ou solicitação..."&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Enviar&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt; &lt;span class="na"&gt;scoped&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nc"&gt;.formulario-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#ccc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.campo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;textarea&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#999&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#4caf50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Veja que usamos o console.log para ver os gatilhos do ciclo.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;onActivated()&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;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 .&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;onDeactivated()​&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;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 .&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3º Componente de AbaDuvidas&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"duvidas-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Dúvidas Frequentes (FAQ)&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Aqui estão as respostas para as perguntas mais comuns.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"faq-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Preciso preencher todos os campos do formulário?&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
        Sim, todos os campos são obrigatórios para que possamos entrar em
        contato de forma eficiente.
      &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"faq-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Qual o prazo de resposta?&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Nossa equipe geralmente responde em até 24 horas úteis.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt; &lt;span class="na"&gt;scoped&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nc"&gt;.duvidas-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#ccc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--black&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.faq-item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;dashed&lt;/span&gt; &lt;span class="m"&gt;#ccc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;h3&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--white&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.1em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Cuidados com o keep alive&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;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).&lt;br&gt;
Usamos o keep alive no lado do cliente, ótimo em aplicações SPA.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Referência:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pt.vuejs.org/guide/built-ins/keep-alive" rel="noopener noreferrer"&gt;https://pt.vuejs.org/guide/built-ins/keep-alive&lt;/a&gt;&lt;br&gt;
&lt;a href="https://learnvue.co/articles/vue-keep-alive" rel="noopener noreferrer"&gt;https://learnvue.co/articles/vue-keep-alive&lt;/a&gt;&lt;br&gt;
&lt;a href="https://pt.vuejs.org/api/composition-api-lifecycle" rel="noopener noreferrer"&gt;https://pt.vuejs.org/api/composition-api-lifecycle&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Nuxt 3 e Cloudflare</title>
      <dc:creator>Helton Carlos Brito Silva</dc:creator>
      <pubDate>Thu, 04 Sep 2025 19:20:19 +0000</pubDate>
      <link>https://dev.to/heltonbrito/nuxt-3-e-cloudflare-h2g</link>
      <guid>https://dev.to/heltonbrito/nuxt-3-e-cloudflare-h2g</guid>
      <description>&lt;p&gt;O Cloudflare Turnstile é uma solução leve, sem CAPTCHA visual, projetada para validar formulários e proteger aplicações contra bots. No Nuxt 3, sua integração pode ser feita de forma simples por meio do módulo nuxt-turnstile.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1º Instalar o módulo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Execute no terminal dentro do projeto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @nuxtjs/turnstile
ou
yarn add @nuxtjs/turnstile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2º Configuração no cloudflare&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Para gerar suas chaves, acesse o Cloudflare, crie uma conta gratuita e vá até a aba Turnstile. Clique em &lt;strong&gt;Adicionar Widget&lt;/strong&gt; e, em seguida, será exibida a página de configuração do widget.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcrg5doofksryftnzbclc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcrg5doofksryftnzbclc.png" alt=" " width="800" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adicione o nome do seu site ou projeto e, em seguida, clique em &lt;strong&gt;Adicionar nomes de host&lt;/strong&gt; para cadastrar o domínio da sua aplicação.&lt;br&gt;
Se você ainda não possui um domínio, pode criar um gratuitamente em um serviço de hospedagem e utilizá-lo apenas para testes. Após isso, insira o domínio no campo indicado e finalize clicando no botão &lt;strong&gt;Adicionar&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Exemplo:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fww05uwlimfr5qnjz9m46.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fww05uwlimfr5qnjz9m46.png" alt=" " width="524" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feito isso, irá gerar duas chaves:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmszxioj5ji0fghpl21g0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmszxioj5ji0fghpl21g0.png" alt=" " width="800" height="207"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3º Criando config no seu projeto&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Crie um arquivo &lt;code&gt;.env&lt;/code&gt; caso não tenha e adicione suas duas chaves. &lt;br&gt;
Os valores a baixo serão apenas ilustrativos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TURNSTILE_SITE_KEY = '1x00000000000000000000AA'
TURNSTILE_SECRET_KEY = '0x4XXXXXXXXXXXXXXS_aacaDSD'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vá ate a arquivo &lt;code&gt;nuxt.config.ts&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default defineNuxtConfig({
  modules: ["@nuxtjs/turnstile"],

  runtimeConfig: {
    turnstile: {
      secretKey: process.env.TURNSTILE_SECRET_KEY, 
    },
    public: {
      turnstile: {
        siteKey: process.env.TURNSTILE_SITE_KEY, 
      }
    }
  }
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Localize o componente no qual deseja integrar o Cloudflare Turnstile. Um exemplo comum é em formulários simples, como login ou cadastro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup lang="ts"&amp;gt;
import { ref } from 'vue'

const form = ref({
  email: '',
  password: ''
})

const turnstileToken = ref('')

const handleSubmit = () =&amp;gt; {
  if (!turnstileToken.value) {
    alert('Valide o Turnstile antes de enviar!')
    return
  }

  console.log('Formulário enviado:', {
    ...form.value,
    turnstileToken: turnstileToken.value
  })
}
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
  &amp;lt;form
    class="max-w-sm mx-auto space-y-6 p-6 border rounded-xl shadow-lg bg-white"
    @submit.prevent="handleSubmit"
  &amp;gt;
    &amp;lt;h2 class="text-2xl font-bold text-center"&amp;gt;Login&amp;lt;/h2&amp;gt;

    &amp;lt;div&amp;gt;
      &amp;lt;label class="block text-sm font-medium mb-1"&amp;gt;Email&amp;lt;/label&amp;gt;
      &amp;lt;input
        v-model="form.email"
        type="email"
        placeholder="E-mail"
        class="w-full px-3 py-2 border rounded-md focus:ring focus:ring-blue-400"
        required
      /&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;div&amp;gt;
      &amp;lt;label class="block text-sm font-medium mb-1"&amp;gt;Senha&amp;lt;/label&amp;gt;
      &amp;lt;input
        v-model="form.password"
        type="password"
        placeholder="Password"
        class="w-full px-3 py-2 border rounded-md focus:ring focus:ring-blue-400"
        required
      /&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;NuxtTurnstile
      v-model="turnstileToken"
      :options="{
        theme: 'auto',
        size: 'normal',
        action: 'login',
        language: 'pt-BR'
      }"
    /&amp;gt;

    &amp;lt;button
      type="submit"
      class="w-full py-2 px-4 bg-blue-600 text-white font-semibold rounded-lg shadow hover:bg-blue-700 transition"
    &amp;gt;
      Entrar
    &amp;lt;/button&amp;gt;
  &amp;lt;/form&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como deve aparecer:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhygrj4p4zq696mghy6mj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhygrj4p4zq696mghy6mj.png" alt=" " width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para validar o token recebido do front-end, você precisa da &lt;strong&gt;key secret&lt;/strong&gt; no lado do seu projeto back-end.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Referência:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nuxt.com/modules/turnstile" rel="noopener noreferrer"&gt;https://nuxt.com/modules/turnstile&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/nuxt-modules/turnstile" rel="noopener noreferrer"&gt;https://github.com/nuxt-modules/turnstile&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nuxt</category>
      <category>vue</category>
    </item>
    <item>
      <title>Nuxt3 e DaisyUi</title>
      <dc:creator>Helton Carlos Brito Silva</dc:creator>
      <pubDate>Wed, 19 Mar 2025 17:22:01 +0000</pubDate>
      <link>https://dev.to/heltonbrito/nuxt3-e-daisyui-3n6f</link>
      <guid>https://dev.to/heltonbrito/nuxt3-e-daisyui-3n6f</guid>
      <description>&lt;p&gt;Torne seu desenvolvimento tailwind CSS mais rápido, limpo e fácil.&lt;/p&gt;

&lt;p&gt;DaisyUI é o plugin Tailwind CSS, você pode usar em diversos Frameworks.&lt;br&gt;
Ele fornece nomes de classe de componente úteis, ajuda a escrever menos código e construir componentes de forma mais rápido, usa um design sofisticado e atual.&lt;/p&gt;

&lt;p&gt;Nos exemplos abaixo irei usar o gerenciador de pacotes npm.&lt;/p&gt;
&lt;h2&gt;
  
  
  1º Etapa - Instalação do Nuxt3.
&lt;/h2&gt;

&lt;p&gt;Para esse exemplo iremos usar o Nuxt3&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm create nuxt project-daisyui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2º Etapa - Adicione o TailwindCss.
&lt;/h2&gt;

&lt;p&gt;Vá para dentro do projeto e adicione esse comando no seu terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev @nuxtjs/tailwindcss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depois vá a modules no arquivo &lt;code&gt;nuxt.config.{ts,js}&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default defineNuxtConfig({
  css: ['~/assets/main.css'],
  modules: [
    '@nuxtjs/tailwindcss'
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depois crie o arquivo &lt;code&gt;main.css&lt;/code&gt; e adicione:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@tailwind base;
@tailwind components;
@tailwind utilities;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Documentação: &lt;a href="https://nuxt.com/modules/tailwindcss" rel="noopener noreferrer"&gt;https://nuxt.com/modules/tailwindcss&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3º Etapa - Adicione o Daisyui.
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -D daisyui@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adicione o arquivo &lt;code&gt;tailwind.config.{ts,js}&lt;/code&gt;, depois coloque o plugin daisyui:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/** @type {import('tailwindcss').Config} */
export default {
  content: [],
  theme: {
    extend: {},
  },
  plugins: [
    require('daisyui'),
  ],
  daisyui: {
    themes: true,
    darkTheme: "dark",
    base: true,
    styled: true, 
    utils: true, 
    prefix: "",
    logs: true,
    themeRoot: ":root",
  },
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caso você utilize o nuxt3 com vite, ele irá mudar um pouco a forma de instalação do plugin, em baixo vou deixar a documentação para instalação:&lt;/p&gt;

&lt;p&gt;Documentação: &lt;a href="https://daisyui.com/docs/install/nuxt/" rel="noopener noreferrer"&gt;https://daisyui.com/docs/install/nuxt/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fiz um exemplos pratico do nuxt3 e daisyui, aqui está o link do meu repositório do github:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Helton-Carlos/nuxt-and-daisyui" rel="noopener noreferrer"&gt;https://github.com/Helton-Carlos/nuxt-and-daisyui&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se quiser já ir testando, já pode colar em seu terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Helton-Carlos/nuxt-and-daisyui.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>tailwindcss</category>
      <category>nuxt</category>
      <category>vue</category>
      <category>css</category>
    </item>
    <item>
      <title>Vue 3 e Naive UI</title>
      <dc:creator>Helton Carlos Brito Silva</dc:creator>
      <pubDate>Tue, 19 Nov 2024 18:32:58 +0000</pubDate>
      <link>https://dev.to/heltonbrito/vue-3-e-naive-ui-1o5d</link>
      <guid>https://dev.to/heltonbrito/vue-3-e-naive-ui-1o5d</guid>
      <description>&lt;p&gt;O Naive UI é uma biblioteca de componentes de interface de usuário (UI) para Vue.js, desenvolvida com foco em simplicidade, design limpo e flexibilidade. 💻💻&lt;/p&gt;

&lt;p&gt;Ela segue o padrão de design "Material Design" e oferece uma vasta gama de componentes prontos para uso, como botões, tabelas, formulários, modais, entre outros, permitindo que os desenvolvedores criem aplicações com interfaces modernas e consistentes de forma rápida e fácil, hoje é uma das minhas bibliotecas favoritas para criação de layouts com Vue3.🚀💻✨&lt;/p&gt;

&lt;h2&gt;
  
  
  1º Etapa
&lt;/h2&gt;

&lt;p&gt;Entre no seu projeto e instale a biblioteca.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -D naive-ui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verifique se instalou &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "devDependencies": {
    "naive-ui": "^2.40.1",
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A versão atual é &lt;code&gt;2.40.1&lt;/code&gt;, pode ser que em algum momento altere, mas acredito que será a mesma forma de instalação.&lt;/p&gt;

&lt;h2&gt;
  
  
  2º Etapa
&lt;/h2&gt;

&lt;p&gt;Hora de usar essa linda biblioteca de componentes!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup lang="ts"&amp;gt;
  import { NButton } from 'naive-ui'
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
  &amp;lt;n-button&amp;gt;naive-ui&amp;lt;/n-button&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para usar de forma global faça isso:&lt;/p&gt;

&lt;p&gt;Adicione também no arquivo &lt;code&gt;main.js&lt;/code&gt; ou &lt;code&gt;main.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createApp } from 'vue'
import App from './App.vue'
import naive from "naive-ui";

createApp(App).use(naive).mount('#app');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora você só precisar fazer isso para usar o button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;n-button&amp;gt;naive-ui&amp;lt;/n-button&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Link da documentação:&lt;br&gt;
&lt;a href="https://www.naiveui.com/en-US/os-theme" rel="noopener noreferrer"&gt;https://www.naiveui.com/en-US/os-theme&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Link de um projeto meu que usa o naive-ui:&lt;br&gt;
&lt;a href="https://github.com/Helton-Carlos/stance-erp" rel="noopener noreferrer"&gt;https://github.com/Helton-Carlos/stance-erp&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv8vtqd3wsgpy1r0vk3bk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv8vtqd3wsgpy1r0vk3bk.png" alt=" " width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Quero agradecer a todos que chegaram ate aqui!
&lt;/h2&gt;

&lt;p&gt;linkedin:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/helton-brito-856ba516b/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/helton-brito-856ba516b/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>naiveui</category>
      <category>vue</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Nuxt 3 e PWA</title>
      <dc:creator>Helton Carlos Brito Silva</dc:creator>
      <pubDate>Fri, 08 Mar 2024 19:15:09 +0000</pubDate>
      <link>https://dev.to/heltonbrito/nuxt-3-e-pwa-36if</link>
      <guid>https://dev.to/heltonbrito/nuxt-3-e-pwa-36if</guid>
      <description>&lt;p&gt;Sabemos que existem muitas maneiras de desenvolver aplicativos. Hoje, vamos falar sobre PWA, uma abordagem muito interessante tanto em termos de tecnologia quanto em custo-benefício.&lt;/p&gt;

&lt;p&gt;Vamos agitar as coisas neste exemplo usando o framework front-end Nuxt 3 com PWA! 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  1º Etapa - Instalação.
&lt;/h2&gt;

&lt;p&gt;Entre no seu projeto feito em nuxt3 e instale o PWA Vite Plugin em seu projeto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i @vite-pwa/nuxt -D 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adicione no &lt;code&gt;nuxt.config.ts&lt;/code&gt; configure-o:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { defineNuxtConfig } from 'nuxt/config'

export default defineNuxtConfig({
  modules: [
    '@vite-pwa/nuxt'
  ],
  pwa: {
    /* PWA options */
  }
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2º Etapa  - Configurar manifest.
&lt;/h2&gt;

&lt;p&gt;É hora de configurar seu projeto para PWA! Vou explicar detalhadamente cada parte que precisa ser configurada no seu projeto.&lt;/p&gt;

&lt;p&gt;vamos começar com o &lt;strong&gt;manifest&lt;/strong&gt; ele define critérios como resiliência, responsividade, conectividade e facilidade de instalação, permitindo que os desenvolvedores criem aplicativos que se comportem de forma semelhante a aplicativos nativos.&lt;/p&gt;

&lt;p&gt;Dentro da pasta &lt;code&gt;public&lt;/code&gt; crie uma pasta chamada &lt;code&gt;manifest&lt;/code&gt; e adicione sua logo do projeto, as imagens devem conter o tamanho descrito dentro do &lt;strong&gt;sizes&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { defineNuxtConfig } from 'nuxt/config'

export default defineNuxtConfig({
  modules: [
    '@vite-pwa/nuxt'
  ],
  pwa: {
   manifest: {
      name: 'nome do seu APP',
      short_name: 'nome simplificado do APP',
      theme_color: '#ffffff',
      start_url:'/',
      lang: 'pt-br',
      description: 'descrição do seu APP',
      screenshots: [
        {
          src: "manifest/home-screen.png",
          sizes: "320x320",
          type: "image/png",
          form_factor: "wide",
          label: "nome simplificado do APP"
        }
      ],
      icons: [
        {
          src: 'manifest/android-chrome-192x192.png',
          sizes: '192x192',
          type: 'image/png',
        },
        {
          src: 'manifest/android-chrome-512x512.png',
          sizes: '512x512',
          type: 'image/png',
        },
        {
          src: 'manifest/android-chrome-512x512.png',
          sizes: '512x512',
          type: 'image/png',
        },
      ],
    },
  }
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uma dica super legal é usar o site: &lt;a href="https://realfavicongenerator.net/" rel="noopener noreferrer"&gt;https://realfavicongenerator.net/&lt;/a&gt;&lt;br&gt;
Ele facilita todo o processo de configurar as medidas necessárias para suas imagens, tudo a partir do logo principal do seu projeto.&lt;/p&gt;
&lt;h2&gt;
  
  
  3º Etapa  - Configuração de strategies.
&lt;/h2&gt;

&lt;p&gt;Na configuração de um PWA com o Workbox, existem duas estratégias principais que podem ser usadas para gerenciar o Service Worker:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;generateSW&lt;/strong&gt;: Esta estratégia é usada para gerar automaticamente um arquivo de Service Worker a partir de uma configuração simples. Ela é mais fácil de configurar, mas pode não oferecer o mesmo nível de controle que a estratégia injectManifest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;injectManifest&lt;/strong&gt;: Esta estratégia permite injetar manualmente uma lista de arquivos para serem precacheados pelo Service Worker. Ela oferece um controle mais granular sobre quais arquivos são armazenados em cache, permitindo uma maior otimização do desempenho e uma experiência offline mais personalizada.&lt;/p&gt;

&lt;p&gt;Neste exemplo iremos configurar na "mão" nossa estrategia para service workers, então usaremos o &lt;strong&gt;injectManifest&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Esta configuração indica que o método de injeção do manifest deve ser usado para gerar o service worker. O método de injeção do manifest permite que você adicione manualmente arquivos ao cache, dando mais controle sobre quais recursos são armazenados em cache. No exemplo dado, globPatterns define os padrões de arquivos que devem ser incluídos no cache. O padrão '*&lt;em&gt;/&lt;/em&gt;.{js,css,html,png,svg,ico}' significa que o Workbox deve considerar todos os arquivos com extensões .js, .css, .html, .png, .svg e .ico para o cache.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { defineNuxtConfig } from 'nuxt/config'

export default defineNuxtConfig({
  modules: [
    '@vite-pwa/nuxt'
  ],
  pwa: {
   strategies:'injectManifest',
   srcDir: 'service-worker',
   filename: 'sw.ts',
   registerType: 'autoUpdate',
   manifest: {
      name: 'nome do seu APP',
      short_name: 'nome simplificado do APP',
      theme_color: '#ffffff',
      start_url:'/',
      lang: 'pt-br',
      description: 'descrição do seu APP',
      screenshots: [
        {
          src: "manifest/home-screen.png",
          sizes: "320x320",
          type: "image/png",
          form_factor: "wide",
          label: "nome simplificado do APP"
        }
      ],
      icons: [
        {
          src: 'manifest/android-chrome-192x192.png',
          sizes: '192x192',
          type: 'image/png',
        },
        {
          src: 'manifest/android-chrome-512x512.png',
          sizes: '512x512',
          type: 'image/png',
        },
        {
          src: 'manifest/android-chrome-512x512.png',
          sizes: '512x512',
          type: 'image/png',
        },
      ],
    },
    workbox: {
      globPatterns: ['**/*.{js,css,html,png,svg,ico}'],
    },
    injectManifest: {
      globPatterns: ['**/*.{js,css,html,png,svg,ico}'],
    },
  }
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Criaremos a pasta chamada: &lt;code&gt;service-worker&lt;/code&gt; com o arquivo: &lt;code&gt;sw.ts&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Dentro do arquivo &lt;code&gt;sw.ts&lt;/code&gt;, iremos chamar o workbox é uma biblioteca JavaScript criada pelo google que simplifica o desenvolvimento de PWAs que utilizam Service Workers. &lt;/p&gt;

&lt;p&gt;Basicamente esse código &lt;strong&gt;precacheAndRoute&lt;/strong&gt; do Workbox serve para precachear e rotear os recursos listados em &lt;strong&gt;self.__WB_MANIFEST&lt;/strong&gt;, que é uma lista gerada automaticamente pelo Workbox durante a compilação.&lt;/p&gt;

&lt;p&gt;Colocaremos esse código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/// &amp;lt;reference lib="WebWorker" /&amp;gt;
/// &amp;lt;reference types="vite/client" /&amp;gt;

import { cleanupOutdatedCaches, createHandlerBoundToURL, precacheAndRoute } from 'workbox-precaching'
import { clientsClaim } from 'workbox-core'
import { NavigationRoute, registerRoute } from 'workbox-routing'

declare let self: ServiceWorkerGlobalScope

precacheAndRoute(self.__WB_MANIFEST);

cleanupOutdatedCaches();

let allowlist: undefined | RegExp[]

if (import.meta.env.DEV)
  allowlist = [/^\/$/]

registerRoute(new NavigationRoute(
  createHandlerBoundToURL('/'),
  { allowlist },
))

self.skipWaiting();
clientsClaim();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Observação:&lt;/strong&gt; Como estamos usando &lt;strong&gt;typeScript&lt;/strong&gt; para escrever seu service worker personalizado. Para resolver os tipos de service workers, basta adicionar WebWorkera no seu &lt;code&gt;tsconfig.json&lt;/code&gt; arquivo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "compilerOptions": {
    "lib": ["ESNext", "DOM", "WebWorker"]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4º Etapa  - Configurar client e devOptions.
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Configurar client:&lt;/strong&gt; Esse trecho de código está relacionado à configuração de um cliente, indica que o aplicativo deve exibir o prompt de instalação quando for detectado que ele pode ser instalado no dispositivo do usuário.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configurar devOptions&lt;/strong&gt;: Habilita as opções de desenvolvimento. Define a rota de fallback para a navegação. Isso significa que se o servidor não encontrar um recurso específico, ele retornará o arquivo especificado, neste caso, a rota raiz.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { defineNuxtConfig } from 'nuxt/config'

export default defineNuxtConfig({
  modules: [
    '@vite-pwa/nuxt'
  ],
  pwa: {
   strategies:'injectManifest',
   srcDir: 'service-worker',
   filename: 'sw.ts',
   registerType: 'autoUpdate',
   manifest: {
      name: 'nome do seu APP',
      short_name: 'nome simplificado do APP',
      theme_color: '#ffffff',
      start_url:'/',
      lang: 'pt-br',
      description: 'descrição do seu APP',
      screenshots: [
        {
          src: "manifest/home-screen.png",
          sizes: "320x320",
          type: "image/png",
          form_factor: "wide",
          label: "nome simplificado do APP"
        }
      ],
      icons: [
        {
          src: 'manifest/android-chrome-192x192.png',
          sizes: '192x192',
          type: 'image/png',
        },
        {
          src: 'manifest/android-chrome-512x512.png',
          sizes: '512x512',
          type: 'image/png',
        },
        {
          src: 'manifest/android-chrome-512x512.png',
          sizes: '512x512',
          type: 'image/png',
        },
      ],
    },
    workbox: {
      globPatterns: ['**/*.{js,css,html,png,svg,ico}'],
    },
    injectManifest: {
      globPatterns: ['**/*.{js,css,html,png,svg,ico}'],
    },
    client: {
      installPrompt: true,
      periodicSyncForUpdates: 20,
    },
    devOptions: {
      enabled: true,
      suppressWarnings: true,
      navigateFallback: '/',
      navigateFallbackAllowlist: [/^\/$/],
      type: 'module',
    },
  }
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quero agradecer a todos que chegaram ate aqui!&lt;br&gt;
linkedin:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/helton-brito-856ba516b/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/helton-brito-856ba516b/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nuxt</category>
      <category>vue</category>
      <category>pwa</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Vue 3 e Testes Unitários</title>
      <dc:creator>Helton Carlos Brito Silva</dc:creator>
      <pubDate>Tue, 23 Jan 2024 19:20:04 +0000</pubDate>
      <link>https://dev.to/heltonbrito/vue-3-e-testes-unitarios-2l7a</link>
      <guid>https://dev.to/heltonbrito/vue-3-e-testes-unitarios-2l7a</guid>
      <description>&lt;p&gt;Na busca pela construção de aplicativos super confiáveis, as empresas estão dando um show ao incentivar seus desenvolvedores front-end a arrasarem nos testes unitários! É a hora de brilhar, galera! 💻✨&lt;/p&gt;

&lt;p&gt;Vamos agitar as coisas neste exemplo usando o framework front-end Vue.js 3, junto com a poderosa dupla Vitest e Vue Test Utils! 🚀 Preparados para a mágica acontecer?&lt;/p&gt;

&lt;h2&gt;
  
  
  1º Etapa
&lt;/h2&gt;

&lt;p&gt;Entre no seu projeto e instale o vitest em seu projeto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -D vitest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vá ate o arquivo &lt;code&gt;package.json&lt;/code&gt; e adicione:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "scripts": {
    "test": "vitest"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adicione também no arquivo &lt;code&gt;vite.config.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  test: {
    globals: true,
    environment: 'jsdom',
  },
})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2º Etapa
&lt;/h2&gt;

&lt;p&gt;Hora de instalar Vue Test Utils, a biblioteca oficial de utilitários de teste para Vue.js!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @vue/test-utils --save-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ao finalizar a instalação, use este comando no terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install jsdom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3º Etapa
&lt;/h2&gt;

&lt;p&gt;É hora de mergulhar de cabeça no código! Vamos agitar as linhas e criar um componente para testar nossa aplicação como verdadeiros mestres da programação! 💻✨ Nesse exemplo incrível, estou prestes a mandar ver dentro do nosso querido componente &lt;code&gt;App.vue&lt;/code&gt;, só para deixar todo mundo afiado nessa aula prática. Preparados para a jornada de aprendizado? 🚀&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import { ref } from 'vue';

const count = ref(0)
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;p data-test="text-value"&amp;gt;
      value: {{ count }}
    &amp;lt;/p&amp;gt;

    &amp;lt;button
      data-test="btn"
      type="button" 
      @click="count++"
    &amp;gt;
      increment
    &amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E depois crie esse arquivo, &lt;code&gt;App.test.js&lt;/code&gt; adicione esse teste:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { mount } from '@vue/test-utils'
import App from './App.vue'

describe("App component", () =&amp;gt; {
  test("Render App", () =&amp;gt; {
    const component = mount(App);

    expect(component).toBeDefined();
  });

  test("Search by text", () =&amp;gt; {
    const wrapper = mount(App);

    expect(wrapper.text()).toContain("value: 0");
  })

  test("triggers a click", () =&amp;gt; {
    const wrapper = mount(App);

    const btn = wrapper.findAll('[data-test="btn"]');

    expect(btn).toHaveLength(1);
  })
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vá ate o terminal e digite:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Resultado final:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkrqqsfw5tirjikk7nmb8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkrqqsfw5tirjikk7nmb8.jpg" alt=" " width="800" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;como podemos ver todos os testes estão aprovados!&lt;/p&gt;

&lt;h2&gt;
  
  
  Quero agradecer a todos que chegaram ate aqui!
&lt;/h2&gt;

&lt;p&gt;linkedin:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/helton-brito-856ba516b/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/helton-brito-856ba516b/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>braziliandevs</category>
    </item>
  </channel>
</rss>
