
⚡ Aprender as bases do Vue 3: de uma pasta vazia a componentes
Está a olhar para Vue 3 e vê uma framework de frontend elegante do grupo das três grandes. React, Angular, Vue: parece coisa séria. Depois abre o primeiro tutorial e lá estão à sua espera o vite, o create-vue e ficheiros .vue com transpiladores... Apesar de, na verdade, poder incluir o Vue com uma única linha <script> e começar a escrever código de imediato. Sem bundlers, sem JSX, sem inferno de configuração.
A distância entre «quero experimentar» e «escrevi um componente» é aqui mais curta do que em qualquer outro lado. Mas a maioria dos tutoriais não encurta essa distância; limitam-se a repetir a documentação aos pedaços, sem dar uma visão completa. Vê fragmentos de sintaxe dispersos e não consegue perceber como é que se transformam numa aplicação.
Este guia é exatamente o percurso que nós próprios fizemos com Vue: de uma pasta vazia a componentes com props. Vai escrever e executar cada linha. Nada de magia, apenas código funcional e a compreensão da reatividade, o principal superpoder do Vue.
💡 Visão geral rápida:
- Construir uma aplicação Vue a partir de uma CDN e montá-la no DOM: a sua primeira instância funcional em 5 minutos
- Percorrer quatro diretivas essenciais, v-for, v-if, v-on e v-bind: os pilares de qualquer template Vue
- Analisar computed e methods: quando fazer cache e quando chamar
- Extrair lógica para componentes e passar dados via props: um passo em direção a uma arquitetura real
Criar uma aplicação Vue
Vamos começar do zero absoluto. Nada de create-vue, vite ou vue-cli, apenas uma pasta com dois ficheiros.
Crie o diretório e os ficheiros no terminal:
1 mkdir vue3-intro 2 cd vue3-intro 3 touch index.html app.js
Ou faça o mesmo através do gestor de ficheiros. Agora abra o index.html e escreva o esqueleto:
1 <!DOCTYPE html> 2 <html lang="ru"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script> 7 <title>Vue 3 — first steps</title> 8 </head> 9 <body> 10 <div id="app"></div> 11 <script src="./app.js"></script> 12 </body> 13 </html>
Três linhas fundamentais. <script src="https://unpkg.com/vue@3/dist/vue.global.js"> carrega o Vue 3 a partir de uma CDN. Esta é a forma mais rápida de começar: a biblioteca carrega como um ficheiro JavaScript normal, sem necessidade de passo de build. <div id="app"> define o ponto de montagem: o local no DOM onde o Vue vai «viver». A terceira linha importa o app.js, onde vamos definir a lógica.
Agora vamos preencher o app.js:
1 const app = Vue.createApp({ 2 data() { 3 return { 4 course: 'Introduction to Vue 3' 5 } 6 } 7 }) 8 9 app.mount('#app')
O método Vue.createApp() cria uma instância da aplicação. Recebe um objeto de opções; aqui declarámos uma propriedade course através da função data(). O Vue torna reativa cada propriedade devolvida por data(): quando um valor muda, o DOM atualiza-se automaticamente. Sem necessidade de manipulação manual da árvore.
Mas a aplicação precisa de ser «ligada» a um elemento na página. É isso que app.mount('#app') faz. Sem esta linha, o Vue não reage a nenhuma alteração: a instância é criada, mas não é iniciada.
Resta apenas exibir a propriedade no HTML. Dentro de <div id="app">, escreva:
1 <h1>{{ course }}</h1>
As chavetas duplas {{ }} são interpolação, a forma principal de exibir dados nos templates Vue. Tudo o que está dentro de {{ }} é substituído pelo Vue pelo valor da propriedade correspondente de data().

Abra o index.html no navegador. A página mostra o texto. A sua primeira aplicação está pronta, e foi você que a escreveu, em vez de a gerar através de uma CLI.
Renderizar listas
Numa aplicação real, quase sempre se trabalha com arrays: produtos, tags, publicações. O Vue fornece a diretiva v-for para isso.
Vamos adicionar um array de tags ao data():
1 const app = Vue.createApp({ 2 data() { 3 return { 4 course: 'Introduction to Vue 3', 5 description: 'Basic guide to Vue 3 for beginners', 6 price: '$19.99', 7 tags: ['Vue', 'Frontend', 'JavaScript'] 8 } 9 } 10 })
E no HTML, uma lista:
1 <ul> 2 <li v-for="tag in tags">{{ tag }}</li> 3 </ul>
A diretiva v-for itera sobre o array tags e cria o seu próprio <li> para cada elemento. A variável tag dentro do ciclo é o elemento atual. O resultado tem este aspeto:

Uma nuance importante: ao iterar sobre um array, cada elemento do DOM precisa de uma chave única. O Vue utiliza-a para rastrear a identidade dos nós durante as atualizações, o que acelera a re-renderização e previne erros relacionados com o estado.
1 <ul> 2 <li v-for="(tag, index) in tags" :key="index">{{ tag }}</li> 3 </ul>
:key é uma abreviatura de v-bind:key, que associa o atributo key ao valor do índice. Se tiver um array de objetos, por exemplo { id: 1, name: 'Vue' }, utilize o id como chave em vez do índice. O índice muda quando a ordem é alterada, enquanto o id é estável, o que o torna mais fiável.
Renderização condicional
Muitas vezes precisa de mostrar ou ocultar um elemento com base numa condição: um botão de compra apenas se o curso estiver disponível. O Vue trata disto com a diretiva v-if.
Vamos adicionar uma flag available ao data():
1 data() { 2 return { 3 course: 'Introduction to Vue 3', 4 description: 'Basic guide to Vue 3 for beginners', 5 price: '$19.99', 6 available: true, 7 tags: [ 8 { id: 1, name: 'Vue' }, 9 { id: 2, name: 'Frontend' }, 10 { id: 3, name: 'JavaScript' } 11 ] 12 } 13 }
E utilizá-la no markup:
1 <p v-if="available">Course available for purchase!</p> 2 <p v-else>Unfortunately, the course is currently unavailable.</p>
O v-if avalia a expressão entre aspas. Se for truthy, o primeiro bloco é renderizado; caso contrário, o v-else entra em ação. Experimente executar app.available = false na consola do navegador e veja a página reagir instantaneamente.

Além de v-if / v-else, existem também o v-else-if para cadeias de condições e o v-show. A diferença é fundamental: o v-if remove completamente o elemento do DOM, enquanto o v-show apenas alterna display: none. Opte por v-if quando a condição muda raramente. Use v-show para alternâncias frequentes, como em separadores, onde o desempenho é relevante.
Gestão de eventos
A diretiva v-on, ou @ para abreviar, escuta eventos do DOM: cliques, input, hover. Quando um evento é disparado, o Vue executa o método ou a expressão especificada.
Vamos adicionar um método purchase às opções da app:
1 const app = Vue.createApp({ 2 data() { 3 return { 4 course: 'Introduction to Vue 3', 5 description: 'Basic guide to Vue 3 for beginners', 6 price: '$19.99', 7 available: true, 8 tags: [ 9 { id: 1, name: 'Vue' }, 10 { id: 2, name: 'Frontend' }, 11 { id: 3, name: 'JavaScript' } 12 ] 13 } 14 }, 15 methods: { 16 purchase() { 17 console.log('Course purchased!') 18 } 19 } 20 })
A secção methods contém funções acessíveis no template e noutros métodos através de this. Agora vamos associar a chamada a um botão:
1 <button @click="purchase">Buy</button>

Para ações simples, pode escrever código diretamente em @click:
1 <button @click="available = !available">Toggle availability</button>

Código inline como este é conveniente para operações curtas, como alternar um sinalizador. Mas mova sempre a lógica complexa para métodos; o template deve permanecer legível. Uma regra simples: counter += 1 é aceitável no template, mas dez linhas de lógica de compra pertencem a um método.
Binding de atributos
Atributos como src, href ou alt precisam frequentemente de ser dinâmicos. A diretiva v-bind, ou : para abreviar, vincula o valor de um atributo a uma expressão Vue.
Vamos adicionar dados para uma imagem:
1 data() { 2 return { 3 // ...other properties 4 imgURL: 'https://catalins.tech/img', 5 imgDescription: 'Photo of a desk with a computer' 6 } 7 }
No template, vincule-os a um <img>:
1 <img :src="imgURL" :alt="imgDescription" width="500" height="350">
A forma completa seria v-bind:src="imgURL"; os dois pontos são apenas açúcar sintático. O Vue agora monitoriza imgURL e imgDescription: altere-os em data() e a imagem na página atualiza-se automaticamente. Isto é a reatividade em ação.

O mesmo princípio aplica-se a atributos como :href, :disabled e :class, bem como a quaisquer outros. Experimente: adicione um link com um href dinâmico a partir de data() e confirme que funciona sem uma única linha extra.
Propriedades computadas
Por vezes, os dados precisam de ser transformados antes da exibição: formatar um preço, concatenar um nome próprio e apelido, verificar uma condição. O Vue disponibiliza propriedades computed para isso.
Imagine que quer ter sempre uma descrição de imagem, mesmo que o campo imgDescription esteja vazio. Vamos escrever uma propriedade computada:
1 const app = Vue.createApp({ 2 data() { 3 return { 4 course: 'Introduction to Vue 3', 5 description: 'Basic guide to Vue 3 for beginners', 6 price: '$19.99', 7 available: true, 8 imgURL: 'https://catalins.tech/img', 9 imgDescription: 'Photo of a desk with a computer', 10 tags: [ 11 { id: 1, name: 'Vue' }, 12 { id: 2, name: 'Frontend' }, 13 { id: 3, name: 'JavaScript' } 14 ] 15 } 16 }, 17 computed: { 18 hasImageDescription() { 19 return this.imgDescription.length > 0 20 ? this.imgDescription 21 : 'Automatic image description' 22 } 23 } 24 })
Agora use a propriedade computada no template em vez dos dados brutos:
1 <img :src="imgURL" :alt="hasImageDescription" width="500" height="350">
O Vue guarda em cache o resultado de uma propriedade computed e recalcula-a apenas quando as suas dependências mudam, no nosso caso imgDescription. Isto é mais eficiente do que chamar uma função em cada renderização.
Uma regra importante: as propriedades computadas destinam-se a exibir dados, não a alterá-los. Não modifique o estado da aplicação dentro de computed; use métodos para isso.
Métodos vs. propriedades computadas
A diferença entre methods e computed resume-se a uma pergunta: está a alterar dados ou a exibir um valor derivado?
As propriedades computadas são para a camada de apresentação. Formatação, filtragem, verificações de condições, concatenação de strings. São armazenadas em cache e não têm efeitos colaterais.
Os métodos são para ações. Alterar um valor em data(), enviar um pedido, alternar um sinalizador. São chamados explicitamente e podem fazer qualquer coisa.
Um anti-padrão típico é modificar this.course dentro de uma propriedade computed. Uma propriedade computada reage a alterações em course, mas não deve alterá-lo ela própria. Use sempre um método para modificar dados. Deixe o template descrever «o que mostrar», não «como calculá-lo».
Componentes e props
À medida que uma aplicação cresce, manter tudo num único ficheiro torna-se ingerível. O Vue permite dividir a interface em componentes: blocos isolados com a sua própria lógica, template e estilos.
Vamos criar o nosso primeiro componente, CourseCard:
1 mkdir components 2 touch components/CourseCard.js
Em components/CourseCard.js, defina o componente:
1 app.component('coursedisplay', { 2 data() { 3 return { 4 course: 'Introduction to Vue 3', 5 description: 'Basic guide to Vue 3 for beginners', 6 price: '$19.99', 7 available: true, 8 imgURL: 'https://catalins.tech/img', 9 imgDescription: 'Photo of a desk with a computer', 10 tags: [ 11 { id: 1, name: 'Vue' }, 12 { id: 2, name: 'Frontend' }, 13 { id: 3, name: 'JavaScript' } 14 ] 15 } 16 }, 17 computed: { 18 hasImageDescription() { 19 return this.imgDescription.length > 0 20 ? this.imgDescription 21 : 'Automatic image description' 22 } 23 }, 24 template: ` 25 <img :src="imgURL" :alt="hasImageDescription" width="500" height="350"> 26 <h1>{{ course }}</h1> 27 <p>{{ description }}</p> 28 <p>{{ price }}</p> 29 <button @click="available = !available">Buy</button> 30 <ul> 31 <li v-for="tag in tags" :key="tag.id">{{ tag.name }}</li> 32 </ul> 33 <p v-if="available">Course available for purchase!</p> 34 <p v-else>Unfortunately, the course is currently unavailable.</p> 35 ` 36 })
O primeiro argumento de app.component() é o nome que usaremos no HTML como tag: <coursedisplay></coursedisplay>. O segundo é um objeto com data(), computed e template, os «internos» do componente.
Agora vamos incluir o componente em index.html e usá-lo:
1 <div id="app"> 2 <coursedisplay></coursedisplay> 3 </div> 4 <script src="./app.js"></script> 5 <script src="./components/CourseCard.js"></script> 6 <script> 7 const mountedApp = app.mount('#app') 8 </script>
Importámos o ficheiro do componente, usámo-lo como uma tag personalizada e montámos a aplicação diretamente no HTML. A lógica do curso está agora encapsulada dentro de CourseCard, enquanto app.js é apenas responsável por criar a instância.
Props: passar dados entre componentes
Props (abreviatura de properties) são o mecanismo para passar dados de um componente pai para um filho. O componente filho declara quais as props que aceita e o pai passa-as como atributos.
Vamos adicionar uma prop paid ao CourseCard que indica se o curso é pago ou gratuito:
1 app.component('coursedisplay', { 2 props: { 3 paid: { 4 type: Boolean 5 } 6 }, 7 // ...rest of the configuration 8 })
O pai, no nosso caso app.js, passa o valor:
1 const app = Vue.createApp({ 2 data() { 3 return { 4 allCourses: 1, 5 paid: true 6 } 7 } 8 })
E em index.html, passamos a prop através de:
1 <coursedisplay :paid="paid"></coursedisplay>
O Vue valida automaticamente o tipo do valor passado. Se for esperado um Boolean mas for recebida uma string, a framework emitirá um aviso na consola. Isto poupa-o a erros parvos à medida que a base de código cresce.
Para tornar uma prop obrigatória, adicione required: true à sua definição. O Vue queixar-se-á se o pai não passar um valor, para que saiba do problema antes de ele quebrar a interface.
Pode encontrar o código completo deste guia no repositório vue3-intro no GitHub, que contém os ficheiros finais index.html, app.js e components/CourseCard.js. Faça um fork e experimente.
Vídeo relacionado
Para reforçar a matéria através da prática, veja a primeira lição do curso Vue 3 do Net Ninja; complementa bem este guia com uma demonstração de código ao vivo:
⁉️🤔 Perguntas frequentes
Posso usar Vue 3 sem um bundler em produção?
Sim, incluí-lo via CDN (
unpkg.com/vue@3/dist/vue.global.js) também funciona em produção. Mas para projetos reais recomendamos mudar para Vite: obtém tree-shaking, divisão de código e Single-File Components, o que simplifica drasticamente o desenvolvimento à medida que a aplicação cresce. O template inicialnpm create vue@latestconfigura tudo isto num minuto.
Como é que v-if difere de v-show?
v-ifremove completamente o elemento do DOM quando a condição é falsa.v-showmantém o elemento no DOM mas alterna a propriedade CSSdisplay: none. Usev-ifquando a condição muda raramente, por exemplo, o perfil de utilizador. Usev-showpara alternâncias frequentes como separadores, onde a velocidade de renderização importa e quer evitar recriar nós.
A:key é obrigatória no v-for?
Tecnicamente,
v-forfunciona sem:key, mas o Vue emitirá um aviso na consola. Sem uma key, a framework não consegue rastrear que elemento do DOM corresponde a que elemento de dados, levando a bugs durante reordenações e eliminações. Especifique sempre:keycom um identificador único, oiddos seus dados e não o índice do array.
Qual é a diferença entre data() e computed?
data()armazena o estado original, os dados «brutos».computedderiva um valor a partir dele para exibição: uma string formatada, um array filtrado, um resultado de validação. Uma propriedade computed atualiza-se automaticamente quando as suas dependências mudam e é armazenada em cache entre renderizações. Os métodos, por outro lado, são chamados de novo a cada vez e destinam-se a ações, não a exibição.
Posso misturar Options API e Composition API?
Sim, pode usar ambos os estilos num único projeto. O Vue 3 suporta totalmente a Options API, enquanto a Composition API é uma ferramenta adicional para cenários complexos. Para aprendizagem, recomendamos começar com a Options API: é mais estruturada e mais próxima do modelo mental de «um componente é um objeto com opções».
O que fazer a seguir: o seu próximo passo com Vue 3
Construiu a sua primeira aplicação, explorou diretivas, propriedades computed e componentes. Esta é a base sobre a qual qualquer projeto é construído, desde uma landing page a um painel de administração.
Há três caminhos a seguir. Primeiro, solidifique através da prática: agarre numa API pública como JSONPlaceholder e exiba uma lista de publicações com filtragem via computed. Segundo, passe para Vite e ficheiros .vue: a documentação oficial do Vue 3 guiá-lo-á do create-vue ao seu primeiro SFC numa hora. Terceiro, aprenda Vue Router e Pinia para construir uma SPA completa.
Se quiser experimentar o Vue sem qualquer instalação, consulte o artigo sobre como incluir o Vue via CDN. E o código inicial deste guia está no repositório vue3-intro; faça um fork e experimente.



