Vue.js
Esta página acompanha os slides acima, na mesma ordem, para você poder alternar entre a explicação detalhada e o resumo visual.
O que é Vue.js
Vue.js é um framework JavaScript de código aberto para construir interfaces de usuário interativas. Ele cuida da camada de visualização, a parte da aplicação que o usuário vê e com a qual interage.
Uma característica importante do Vue é a adoção incremental. Você não precisa reescrever o projeto inteiro para usá-lo: dá para começar controlando apenas um pedaço de uma página que já existe e, aos poucos, ampliar o uso.
Uma analogia: se o HTML são as paredes de uma casa e o CSS é a pintura, o JavaScript tradicional seria instalar e ligar à mão cada interruptor e cada tomada. O Vue funciona como um sistema de automação residencial: você declara o que deve acontecer (“quando escurecer, acenda a luz da sala”) e ele mantém tudo sincronizado sozinho.
Por que usar Vue?
- Simplicidade: você escreve um HTML quase normal, com alguns atributos especiais. A curva de aprendizado é suave.
- Componentização: a interface é dividida em peças reutilizáveis, como blocos de LEGO.
- Ecossistema: ferramentas oficiais como o Vue Router (navegação entre páginas) e o Pinia (gerenciamento de estado) resolvem necessidades comuns.
Reatividade
A grande ideia do Vue é a reatividade: quando um dado muda, a tela se atualiza sozinha. Pense em uma planilha eletrônica. Ao alterar o valor de uma célula, todas as fórmulas que dependem dela são recalculadas automaticamente.
Sem Vue, cada mudança exige que você encontre o elemento e altere o conteúdo:
document.getElementById("msg").innerText = "novo valor";
Com Vue, você só altera a variável. O Vue sabe quais partes da tela dependem dela e as atualiza. O ciclo completo fica assim:
flowchart TD
dados["data: dados reativos"] --> template[Template com diretivas]
template --> tela[Tela atualizada]
usuario[Evento do usuario] --> metodos[methods]
metodos --> dados
Os dados ficam em data(). O template (o HTML) mostra esses dados. Quando o usuário clica ou digita, um método altera os dados, e a tela acompanha.
Hello Vue
O primeiro exemplo exibe a mensagem “Hello Vue in CPW2!” na tela:
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<title>Hello Vue</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.global.min.js">
</script>
</head>
<body>
<div id="app">
<h1>{{ message }}</h1>
</div>
<script>
const app = Vue.createApp({
data() {
return {
message: 'Hello Vue in CPW2!'
}
}
})
app.mount('#app')
</script>
</body>
</html>
Vamos ler o exemplo por partes:
- Importação via CDN: a tag
<script src="...vue.global.min.js">carrega o Vue direto da internet. Nada precisa ser instalado, o que é ótimo para aprender e prototipar. - O território do Vue: a
<div id="app">é a região que o Vue controla. Fora dela, a página continua sendo HTML comum. - Interpolação
{{ message }}: as chaves duplas (os “bigodes”, do inglês mustache) dizem ao Vue: “coloque aqui o valor demessage”. Se o valor mudar, o texto muda junto. Vue.createApp({...}): cria a aplicação. A funçãodata()devolve um objeto com os dados reativos. Ela é uma função, e não um objeto direto, para que cada componente receba a sua própria cópia dos dados.app.mount('#app'): liga a aplicação àdiv. Antes dessa linha, o Vue existe na memória, mas ainda não controla nada na página.
Diretivas
Diretivas são atributos especiais que o Vue acrescenta ao HTML. Todas começam com v- e dizem ao Vue como aquele elemento deve se comportar. As principais são:
v-bind: liga um atributo HTML a um dado.v-model: liga um campo de formulário a um dado nos dois sentidos.v-ifev-else: mostram ou removem um elemento conforme uma condição.v-for: repete um elemento para cada item de uma lista.v-on: executa um método quando acontece um evento, como um clique.
As próximas seções mostram cada uma delas em um exemplo pequeno e completo.
v-model: ligação de mão dupla
A diretiva v-model conecta um campo de formulário a uma variável. A ligação vale nos dois sentidos: o que o usuário digita vai para a variável, e o que o código coloca na variável aparece no campo. É como um espelho.
<div id="app">
<p>{{ message }}</p>
<p><input v-model="message"></p>
</div>
<script>
const app = Vue.createApp({
data() {
return { message: 'Hello Vue.js in CPW2!' }
}
})
app.mount('#app')
</script>
Ao digitar no <input>, o parágrafo acima muda letra por letra. Nenhum código de evento foi escrito. Em JavaScript puro, seria preciso ouvir o evento input, ler o valor do campo e escrever esse valor no parágrafo.
v-for: listas
A diretiva v-for cria um elemento para cada item de um array. É um laço de repetição escrito direto no HTML.
<div id="app">
<ul>
<li v-for="x in task">
{{ x.text }}
</li>
</ul>
</div>
<script>
const app = Vue.createApp({
data() {
return {
task: [
{ text: 'Learn JavaScript' },
{ text: 'Learn Vue.js' },
{ text: 'Build Something Awesome' }
]
}
}
})
app.mount('#app')
</script>
Leia v-for="x in task" como “para cada elemento x dentro do array task”. Três objetos no array geram três <li> na tela. Se um item for acrescentado ou removido do array, a lista se atualiza sozinha.
v-if e v-else: renderização condicional
A diretiva v-if mostra um elemento apenas quando a condição é verdadeira. O v-else, colocado logo depois, mostra a alternativa. É um if/else aplicado ao HTML.
<div id="app">
<h1 v-if="show">Vue é incrível!</h1>
<h1 v-else>Oh não 😢</h1>
<template v-if="show">
<p>Parágrafo 1</p>
<p>Parágrafo 2</p>
</template>
</div>
<script>
const app = Vue.createApp({
data() {
return { show: true }
}
})
app.mount('#app')
</script>
Com show igual a true, aparece “Vue é incrível!”. Com false, aparece “Oh não”. A tag <template> aplica a condição a um grupo de elementos sem criar um elemento extra na página.
Um detalhe importante: v-if remove o elemento do DOM quando a condição é falsa. Se a ideia for apenas esconder, mantendo o elemento no DOM, use v-show. O v-show só troca o estilo display do elemento, o que é mais barato quando algo aparece e some muitas vezes.
v-on: eventos
A diretiva v-on faz o Vue reagir a eventos do usuário: cliques, teclas, movimentos do mouse. A forma v-on:click tem um atalho muito usado, @click.
<div id="app">
<button v-on:click="execute">Try</button>
</div>
<script>
const app = Vue.createApp({
data() {
return {}
},
methods: {
execute(event) {
alert(event.target.tagName)
}
}
})
app.mount('#app')
</script>
v-on:click="execute" significa “quando este botão for clicado, chame o método execute”. Os métodos ficam no objeto methods. O parâmetro event é o evento nativo do navegador, e event.target é o elemento clicado (aqui, o BUTTON).
Dentro de um método, this dá acesso aos dados de data(). É assim que um evento altera o estado da aplicação:
<div id="app">
<p>Cliques: {{ total }}</p>
<button @click="contar">Clique aqui</button>
</div>
<script>
const app = Vue.createApp({
data() {
return { total: 0 }
},
methods: {
contar() {
this.total++
}
}
})
app.mount('#app')
</script>
v-bind: atributos dinâmicos
A interpolação {{ }} funciona apenas no conteúdo dos elementos, não dentro de atributos. Para que um atributo receba um valor vindo dos dados, use v-bind. O atalho é o sinal de dois pontos: :src é o mesmo que v-bind:src.
<div id="app">
<img :src="foto" :alt="descricao" width="200">
<button :disabled="bloqueado">Enviar</button>
</div>
<script>
const app = Vue.createApp({
data() {
return {
foto: 'https://vuejs.org/images/logo.png',
descricao: 'Logo do Vue',
bloqueado: true
}
}
})
app.mount('#app')
</script>
Sem os dois pontos, src="foto" seria o texto literal “foto”. Com :src, o Vue lê a variável foto e usa o seu valor. Trocar bloqueado para false habilita o botão.
Resumo das diretivas
| Diretiva | Função | Atalho |
|---|---|---|
v-bind | Liga um atributo HTML a um dado | : |
v-model | Ligação de mão dupla com campos de formulário | |
v-if / v-else | Renderização condicional | |
v-for | Repete um elemento para cada item de uma lista | |
v-on | Reage a eventos do DOM | @ |
Ciclo de vida
Todo componente Vue passa por fases, da criação até a remoção da página, assim como um ser vivo nasce, cresce e morre. Em cada fase o Vue chama funções especiais, os ganchos (hooks), onde você pode colocar código.
- Criação (
beforeCreate,created): o Vue prepara dados e métodos. - Montagem (
beforeMount,mounted): o componente é inserido no DOM. - Atualização (
beforeUpdate,updated): o DOM é atualizado depois que um dado muda. - Desmontagem (
beforeUnmount,unmounted): o componente sai do DOM.
Os ganchos mais usados no dia a dia:
created: os dados já existem, mas nada foi desenhado na tela. Bom lugar para começar a buscar dados de uma API.mounted: o componente já está visível. Bom lugar para acessar elementos do DOM, por exemplo para dar foco a um campo.updated: roda a cada atualização da tela. Cuidado: alterar dados aqui pode gerar um laço infinito de atualizações.unmounted: hora de limpar a casa, parando timers (clearInterval) e removendo ouvintes de eventos. Esquecer essa limpeza deixa código rodando para um componente que não existe mais.
Os ganchos são declarados como funções no mesmo objeto de data() e methods:
const app = Vue.createApp({
data() {
return { segundos: 0, timer: null }
},
mounted() {
this.timer = setInterval(() => this.segundos++, 1000)
},
unmounted() {
clearInterval(this.timer)
}
})
app.mount('#app')
Quando a aplicação aparece na tela, mounted inicia um cronômetro. Se ela for removida, unmounted para o cronômetro.
Integração com a Fetch API
A Fetch API já vem no navegador: não precisa de biblioteca extra. Ela funciona como um carteiro: leva o pedido ao servidor e traz a resposta de volta. Cada chamada de fetch devolve uma Promise, o mesmo conceito estudado na aula de Promise.
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.global.min.js"></script>
</head>
<body>
<div id="app">
<button v-on:click="getData">Load data</button>
<ul>
<li v-for="x in tasks">
{{ x.text }}
</li>
</ul>
</div>
<script>
const app = Vue.createApp({
data() {
return { tasks: [] }
},
methods: {
getData() {
fetch("data.json")
.then(response => response.json())
.then(data => (this.tasks = data))
}
}
})
app.mount('#app')
</script>
</body>
O fluxo, passo a passo:
- O usuário clica em “Load data”, e o
v-on:clickchamagetData. fetch("data.json")faz a requisição e devolve uma Promise.- O primeiro
.then()recebe o objetoResponse.response.json()lê o corpo e devolve outra Promise, já convertida em objeto. - O segundo
.then()coloca esses dados emthis.tasks. Comotasksé reativo, ov-fordesenha a lista na tela.
O mesmo método pode ser escrito com async/await, que você já conhece:
methods: {
async getData() {
try {
let response = await fetch("data.json")
this.tasks = await response.json()
} catch (erro) {
console.error(erro)
}
}
}
Para o fetch conseguir ler o data.json, abra a página por um servidor local (por exemplo, a extensão Live Server do VS Code), e não pelo arquivo direto no navegador.
Próximos passos
Quando a aplicação cresce, o próximo passo é organizar a interface em componentes, inclusive em arquivos .vue. Em projetos maiores, o Nuxt.js entra com roteamento, páginas e estrutura de projeto.
Exercícios de Fixação Práticos
Os exercícios abaixo são progressivos: cada um acrescenta uma peça ao anterior. Use uma página HTML simples com o Vue carregado por CDN, como no Hello Vue, e confira o resultado direto na tela. Se travar em algum, volte à seção indicada entre parênteses.
-
Minha primeira aplicação (Hello Vue)
Crie uma página com uma
<div id="app">e uma aplicação Vue com um dadonomecontendo o seu nome. Mostre na tela a fraseOlá, {{ nome }}!dentro de um<h1>. Depois, troque o valor denomeno código e recarregue a página para ver a mudança. -
O espelho (v-model)
Acrescente um
<input>ligado anomecomv-model. Ao digitar no campo, o<h1>do exercício anterior deve mudar a cada letra. -
Atributo dinâmico (v-bind)
Crie um dado
corDoTextocom o valor"blue"e use:style="{ color: corDoTexto }"no<h1>. Acrescente um segundo<input>ligado acorDoTextocomv-modele teste digitarred,greenouorange. -
Mostrar e esconder (v-if, v-else e v-on)
Crie um dado
visivelcom valortruee um botão com@click="visivel = !visivel". Quandovisivelfor verdadeiro, mostre um parágrafo com uma dica de estudo; quando for falso, mostre “Dica escondida”. Depois troquev-ifporv-showe observe, no inspetor do navegador, a diferença no DOM. -
Lista de frutas (v-for)
Crie um dado
frutascom o array["Maçã", "Banana", "Uva"]. Usev-forpara mostrar cada fruta em um<li>dentro de uma<ul>. Acrescente uma quarta fruta no array e confira que a lista cresce sem mexer no HTML. -
Contador (v-on e methods)
Crie um dado
totalcomeçando em 0 e dois botões: “+1” e “Zerar”. Cada botão chama um método diferente emmethods(somarezerar), que alterathis.total. Mostre o total na tela. -
Lista de tarefas (v-model, v-on, v-for e v-if juntos)
Crie um
<input>ligado anovaTarefae um botão “Adicionar”. Ao clicar, um método coloca o texto no arraytarefascompushe limpa o campo. Mostre as tarefas comv-for. Quando o array estiver vazio, mostre comv-ifa mensagem “Nenhuma tarefa cadastrada”. Como desafio extra, ignore textos vazios e acrescente um botão “Remover” em cada<li>usandosplice. -
Tarefas vindas de um JSON (Fetch API)
Crie um arquivo
tarefas.jsonna mesma pasta da página, por exemplo[{ "texto": "Estudar Vue" }, { "texto": "Fazer os exercícios" }]. Crie um botão “Carregar” que chama um método comfetch("tarefas.json"). No primeiro.then(), converta a resposta comresponse.json(). No segundo, guarde os dados emtarefase mostre a lista comv-for. Abra a página por um servidor local. -
Carregar sem clicar (ciclo de vida e async/await)
Reescreva o exercício 8 sem o botão: faça a requisição no gancho
mounted, usandoasync/awaitetry/catch. Se a requisição falhar (teste trocando o nome do arquivo), mostre comv-ifa mensagem “Não foi possível carregar as tarefas”.
Depois de concluir estes exercícios, siga para os Exercícios de projeto sobre Vue.js, que constroem um CRUD completo com componentes e uma API.
Exercício de Fixação Teórico
Referências
-
O que é Vue.js? no W3Schools
-
Vue.js: The Progressive JavaScript Framework
-
Fetch API: requisições HTTP nativas do navegador

CC BY 4.0 DEED