VueJs: guia completo
Guia completo de como instalar e utilizar o VueJs. Veja quais são e como aplicar os principais recursos com passo-a-passo e exemplos práticos.
VueJs
é um framework
progressivo e reativo de código aberto utilizado para desenvolvimento de interfaces
e SPA's.
A primeira versão do VueJs
foi lançada em fevereiro de 2014 por um ex-funcionário do Google
chamado Evan You.
É um dos frameworks
mais populares e utilizados atualmente, com cerca de 190k estrelas no GitHub
. Tem como foco a
camada de visão, e um dos princípios é simplificar o desenvolvimento web e poder ser incluído em projetos já existente
sem grandes dificuldades.
A instalação é simples e um projeto pode ser iniciado com uma estrutura de pastas básicas já definidas sem muita dificuldade.
Principais funcionalidades
Algumas das funcionalidades importantes do VueJs
são explicadas abaixo(ordem alfabética).
Animação/Transição
VueJs
tem por padrão várias formas de aplicar transições aos elementos HTML
quando estes são adicionados, removidos
ou atualizados do DOM
.
VueJs
inclui um componente que precisa ser colocado como pai do elemento que irá receber o efeito de transição, e pode
ser facilmente customizado para adicionar mais interatividade a interface.
Também existem várias animações criadas pela comunidade disponíveis para serem utilizadas em qualquer projeto.
Componente
Um componente(component
) é um elemento que pode ser reaproveitado em várias partes do código, muito útil para evitar
repetições desnecessárias. Pode ser apenas a parte visual, mas também pode conter uma regra de negócio que será
replicada em vários contextos.
Dado computado
Um dado computado (Computed Properties
) funciona como uma variável padrão, porém responde a qualquer alteração nos
dados que impactar em seu valor.
Na prática, é bem útil e evita utilizar a diretiva v-on
em muitos casos, deixando a interface do usuário ainda mais
fluída.
Diretiva
Diretivas ou Directives no VueJs são semelhantes ao visto em outras linguagens, alguns exemplos facilmente reconhecíveis são:
- v-if
- v-else-if
- v-else
- v-show
- v-on
- v-bind
- v-model
São utilizadas no front-end da aplicação sendo responsáveis por boa parte das interações do usuário.
DOM Virtual
O DOM
(Document Object Model
) é a interface entre o JavaScript
e os objetos visíveis do HTML
.
O VueJs
, assim como outros frameworks
, como, por exemplo, Ember
e React
não fazem alterações diretamente
no DOM
, ao invés disso, uma réplica do DOM
é criada e representada como uma estrutura de dados do JavaScript
.
Quando alguma alteração na interface acontece, ela é efetuada inicialmente na estrutura de dados do JavaScript
, e após
isso comparada com o DOM
original. Após isso, caso necessário a alteração é efetuada no DOM
original e se torna
visível ao usuário.
Utilizar o DOM
virtual traz vários benefícios de desempenho, pois é menos custoso computacionalmente e oferece uma
frequência de atualização superior comparado a atualizar a interface diretamente.
Escuta de eventos
Escuta de eventos, ou em inglês, event handling
é o fato de esperar algum evento ser disparado para executar algum
código com esse gatilho.
Em VueJs
a diretiva v-on
é utilizada para esse propósito.
interligação de dados
A interligação de dados, ou em inglês, data binding
, é o fato de associar uma variável a um atributo HTML
, bastando
alterar essa variável e o conteúdo desse atributo será alterado como consequência.
Essa interligação pode ser realizada para o style
, class ou praticamente qualquer outro atributo do HTML
.
A diretiva responsável por essa funcionalidade no VueJs
é o v-bind
.
Leveza
Um script
em VueJs
costuma ser muito leve, o que geralmente garante uma alta desempenho.
Observador
Observadores (Watchers
) são responsáveis por reagir à mudança de dados, por exemplo, em um formulário.
Utilizar um observador abstrai boa parte das tarefas necessárias para isso quando não se utiliza um framework
.
Rotas
A navegação entre páginas também é abstraída no Vuejs
com a ajuda de um componente chamado vue-router
.
Template
Os templates do VueJs
tem uma sintaxe baseada no HTML
, porém com seus valores associados com o DOM
virtual e a
instância
VueJs
a qual é correspondente.
Os templates são compilados com as Render Functions
do DOM
virtual e podem ser substituídas pelo usuário com a
própria
render function
.
Vue-CLI
A interface de linha de comando do VueJs
trazem várias funcionalidades e abstrai vários processos, inclusive adição de
componentes, a etapa de build
e até a criação do projeto.
Comparações
No site oficial do VueJs
estão presentes estas comparações, caso queira o original, em inglês
está aqui, a versão traduzida(e um pouco desatualizada)
está aqui.
Na documentação são comparados:
- ReactJs vs VueJs
- AngularJs vs VueJs
- Angular vs VueJs
- Ember vs VueJs
- Knockout vs VueJs
- Polymeter vs VueJs
- Riot vs VueJs
Como adicionar VueJs ao projeto?
Existem várias formas de adicionar o VueJs
ao seu projeto, veremos algumas logo abaixo.
No restante do artigo partiremos da criação utilizando a interface de linha de comando do VueJs
(CLI
), por facilitar
já deixando pronto uma boa estrutura de pastas.
Tag script
Uma forma simples é baixando o VueJs
e colocando o numa tag
<script>
como o caminho correto. Vue será registrado
como uma variável global nesses casos.
Ao acessar o link de download você verá duas versões, uma de desenvolvimento e outra de produção.
A única diferença é que a versão de desenvolvimento irá exibir erros e conterá um modo debug
, enquanto a versão de
produção não contém isso e também não tem o código organizado visando a legibilidade e sim a economia de tamanho(33.46
KB).
<html>
<head>
<script src="/rota/para/vue.js" type="text/javascript"></script>
</head>
<body></body>
</html>
CDN
VueJs
também pode ser instalado com a ajuda de um CDN
, ele está presente em vários, abaixo temos o exemplo da última
versão utilizando o jsdelivr
:
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body></body>
</html>
Também está disponível no unpkg
e no cdnjs
.
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.js"></script>
Em todos os exemplos esta sendo utilizado a versão de desenvolvimento, caso queira a versão de produção basta
substituir /vue.js
por /vue.min.js
.
Também existe uma versão nativa ES
, que é compatível com o build
ES
padrão.
<script type="module">
import Vue from 'https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.esm.browser.js'
</script>
NPM
Esta é a forma de instalação recomendada para aplicações grandes feitas em VueJs
. É compatível com Webpack
e Browserify
.
Para instalar basta utilizar o NPM
como feito com qualquer outro módulo.
npm install vue
CLI
A interface de linha de comando do VueJs
é bem prática e intuitiva de ser utilizada, para instalar basta utilizar
o npm
da seguinte forma.
npm install -g @vue/cli
Depois de alguns minutos a instalação será concluída, para iniciar um projeto basta utilizar o vue create
,
substituindo o <nome-do-projeto>
pelo nome do projeto.
vue create <nome-do-projeto>
Estrutura de um projeto em VueJs
Se você criou o projeto utilizando o CLI
do VueJs
, terá algo semelhante ao mostrado abaixo.
.
├── babel.config.js
├── package.json
├── package-lock.json
├── public
│ ├── favicon.ico
│ └── index.html
├── README.md
└── src
├── App.vue
├── assets
│ └── logo.png
├── components
│ └── HelloWorld.vue
└── main.js
Desenvolvendo uma aplicação em VueJs
Para utilizar as principais funcionalidades do VueJs
que foram mostradas anteriormente, realizaremos uma aplicação
simples, uma calculadora de IMC.
Porquê? Pois, com isso poderemos cobrir várias utilidades comuns no dia-a-dia, e inclusive algumas mais específicas que
podem ser uteis em algum momento na sua jornada desenvolvendo em VueJs
.
Para esse mini-projeto partiremos daquela estrutura básica mostrada anteriormente.
Rodando a aplicação
Inicialmente vamos rodar a aplicação em modo de desenvolvimento, na pasta raiz do projeto, basta executar o comando abaixo.
vue-cli-service serve
Se a parte da instalação e criação do projeto com o CLI
foi feita corretamente, você deve conseguir abrir o
link http://localhost:8080/
e ver algo semelhante ao mostrado na imagem abaixo.
Preparando os arquivos
Simplificaremos um pouco substituindo o conteúdo do arquivo App.vue
com a menor quantidade de código possível.
<template>
<div>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
</style>
Podemos excluir os arquivos src/assets/logo.png
e src/components/HelloWorld.vue
, pois não os utilizaremos e
dependendo da IDE
e sua configuração pode ser que apareça algumas mensagens de erros. A estrutura do projeto ficará da
seguinte forma.
.
├── babel.config.js
├── package.json
├── package-lock.json
├── public
│ ├── favicon.ico
│ └── index.html
├── README.md
└── src
├── App.vue
├── assets
│ └── logo.png
├── components
│ └── HelloWorld.vue
└── main.js
Adicionando css
Para não atrasar muito o desenvolvimento podemos utilizar algum framework
css
, no exemplo utilizaremos C por ser o
mais popular.
Existem várias formas de se incluir o bootstrap
em um projeto em VueJs
, prezando pela simplicidade, legibilidade e
acessibilidade do artigo para todos, independente do nível de conhecimento, conduziremos simplesmente importando o
arquivo css
a partir do cdn
.
Para isto basta editar o arquivo App.vue
adicionando o @import
na tag de style
, da seguinte forma.
<style>
@import "https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css";
</style>
Desenvolvendo o layout da aplicação
Para o cálculo do IMC, precisaremos de duas informações apenas, a altura e o peso(massa) do usuário, então criaremos um
formulário simples pedindo esses dados alterando a parte template
do arquivo App.vue
.
<template>
<div class="d-flex justify-content-center">
<div>
<h1>Cálculo IMC</h1>
<div class="mb-3">
<label class="form-label">Massa em KG:</label>
<input class="form-control" type="number">
</div>
<div>
<label class="form-label">Altura em metros:</label>
<input class="form-control" type="number">
</div>
</div>
</div>
</template>
Como utilizaremos reatividade, não precisaremos de um botão para submeter esse formulário.
v-model
Agora utilizaremos uma das diretivas mais incríveis do VueJs, o v-model
, dessa forma poderemos sincronizar uma
variável com uma tag <input>
do HTML
, primeiro definiremos uma função data
no corpo da tag script
do VueJs
que
retorna as propriedades com reatividade, as propriedades que definiremos serão apenas duas: massa
e altura
.
<script>
export default {
name: 'App',
data() {
return {
massa: 0,
altura: 0
}
}
}
</script>
Colocaremos ambas as propriedades como valor da diretiva v-model
na tag
<input>
correspondente. Para observarmos a
reatividade em ação, vamos apenas exibir ambas as propriedades na tela colocando elas em chaves duplas({{ }}
).
<template>
<div class="d-flex justify-content-center">
<div>
<h1>Cálculo IMC</h1>
<div class="mb-3">
<label class="form-label">Massa em KG:</label>
<input v-model="massa" class="form-control" type="number">
</div>
<div class="mb-3">
<label class="form-label">Altura em metros:</label>
<input v-model="altura" class="form-control" type="number">
</div>
<p>Massa: {{ massa }} KG</p>
<p>Altura: {{ altura }} metros</p>
</div>
</div>
</template>
Abrindo no navegador você observará a mágica acontecer, onde basta alterar o valor do input
e este valor será
atualizado em tempo real nos parágrafos imediatamente abaixo.
Propriedade computada
Agora calcularemos o IMC, existem várias formas de fazer isso, mas a mais simples é utilizando uma computed property
,
onde o seu valor será recalculado apenas quando alguma de suas dependências forem alteradas.
Para isso adicionaremos uma chave computed
no objeto sendo exportado no arquivo App.vue
, que ficará com o seguinte
conteúdo.
<script>
export default {
name: 'App',
data() {
return {
massa: 0,
altura: 0
}
},
computed: {
imc: function () {
return this.massa / (this.altura ** 2)
}
}
}
</script>
Para esse valor ser visível na tela, podemos utilizar no template
semelhantemente ao que foi efetuado com os atributos
em data
.
<template>
<div class="d-flex justify-content-center">
<div>
<h1>Cálculo IMC</h1>
<div class="mb-3">
<label class="form-label">Massa em KG:</label>
<input v-model="massa" class="form-control" type="number">
</div>
<div class="mb-3">
<label class="form-label">Altura em metros:</label>
<input v-model="altura" class="form-control" type="number">
</div>
<p>Massa: {{ massa }} KG</p>
<p>Altura: {{ altura }} metros</p>
<p>IMC: {{ imc }}</p>
</div>
</div>
</template>
Acessando o site agora e preenchendo as informações, veremos o IMC sendo atualizado e exibido na tela em tempo real.
v-if
Você provavelmente reparou que quando os dados não estão preenchidos, ou estão incorretos, como no caso da altura ser 0,
um texto não muito amigável será exibido na tela, para resolver esse problema utilizaremos a diretiva v-if
, que irá
exibir o IMC apenas caso os valores sejam preenchidos e diferentes de zero.
Para isso, calcularemos o IMC apenas caso os dados sejam válidos, caso não sejam, retornaremos false
.
<template>
<div class="d-flex justify-content-center">
<div>
<h1>Cálculo IMC</h1>
<div class="mb-3">
<label class="form-label">Massa em KG:</label>
<input v-model="massa" class="form-control" type="number">
</div>
<div class="mb-3">
<label class="form-label">Altura em metros:</label>
<input v-model="altura" class="form-control" type="number">
</div>
<p>Massa: {{ massa }} KG</p>
<p>Altura: {{ altura }} metros</p>
<p v-if="imc">IMC: {{ imc }}</p>
</div>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
massa: 0,
altura: 0
}
},
computed: {
imc: function () {
if (this.massa === null || this.altura == null) {
return false
} else if (parseFloat(this.massa) === 0 || parseFloat(this.altura) === 0) {
return false
} else {
return this.massa / (this.altura ** 2)
}
}
}
}
</script>
Assim como podemos utilizar v-if
, podemos utilizar a diretiva v-else
para exibir um parágrafo solicitando que o
usuário preencha os dados.
<template>
<div class="d-flex justify-content-center">
<div>
<h1>Cálculo IMC</h1>
<div class="mb-3">
<label class="form-label">Massa em KG:</label>
<input v-model="massa" class="form-control" type="number">
</div>
<div class="mb-3">
<label class="form-label">Altura em metros:</label>
<input v-model="altura" class="form-control" type="number">
</div>
<p>Massa: {{ massa }} KG</p>
<p>Altura: {{ altura }} metros</p>
<p v-if="imc">IMC: {{ imc }}</p>
<p v-else>Preencha os dados corretamene!</p>
</div>
</div>
</template>
Caso os dados não estejam corretos, a mensagem será exibida ao invés do IMC.
Criado um componente
Agora que já temos essa funcionalidade pronto, exploraremos uma funcionalidade muito útil do VueJs que são os
componentes, para isso criaremos um arquivo no caminho src/components/
chamado CalculadoraIMC.vue
com o conteúdo
base de um componente.
<template>
</template>
<script>
export default {
name: "CalculadoraIMC"
}
</script>
A estrutura de pastas agora ficou da forma mostrada abaixo.
.
├── babel.config.js
├── package.json
├── package-lock.json
├── public
│ ├── favicon.ico
│ └── index.html
├── README.md
└── src
├── App.vue
├── assets
├── components
│ └── CalculadoraIMC.vue
└── main.js
Adicionaremos o conteúdo responsável pela função da calculadora no arquivo CalculadoraIMC.vue
.
<template>
<div>
<h1>Cálculo IMC</h1>
<div class="mb-3">
<label class="form-label">Massa em KG:</label>
<input v-model="massa" class="form-control" type="number">
</div>
<div class="mb-3">
<label class="form-label">Altura em metros:</label>
<input v-model="altura" class="form-control" type="number">
</div>
<p>Massa: {{ massa }} KG</p>
<p>Altura: {{ altura }} metros</p>
<p v-if="imc">IMC: {{ imc }}</p>
<p v-else>Preencha os dados corretamene!</p>
</div>
</template>
<script>
export default {
name: "CalculadoraIMC",
data() {
return {
massa: 0,
altura: 0
}
},
computed: {
imc: function () {
if (this.massa === null || this.altura == null) {
return false
} else if (parseFloat(this.massa) === 0 || parseFloat(this.altura) === 0) {
return false
} else {
return this.massa / (this.altura ** 2)
}
}
}
}
</script>
Agora vamos importar e utilizar esse componente no arquivo App.vue
.
<template>
<div class="d-flex justify-content-center">
<CalculadoraIMC></CalculadoraIMC>
</div>
</template>
<script>
import CalculadoraIMC from "@/components/CalculadoraIMC";
export default {
name: 'App', components: {CalculadoraIMC}
}
</script>
<style>
@import "https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css";
</style>
Dessa forma temos todas as funcionalidades da calculadora em apenas uma linha, e podemos utilizar o mesmo componente em várias páginas ou múltiplas vezes na mesma página.
binding de classe
Às vezes queremos dar destaque para uma mensagem dependendo do seu valor, no exemplo da calculadora de IMC poderíamos
deixar o texto do parágrafo destacado caso o IMC seja maior que trinta, para isso podemos fazer um biding
de classe,
utilizando a classe text-warning
do bootstrap.
Abaixo temos essa alteração efetuada no arquivo CalculadoraIMC.vue
.
<template>
<div>
<h1>Cálculo IMC</h1>
<div class="mb-3">
<label class="form-label">Massa em KG:</label>
<input v-model="massa" class="form-control" type="number">
</div>
<div class="mb-3">
<label class="form-label">Altura em metros:</label>
<input v-model="altura" class="form-control" type="number">
</div>
<p>Massa: {{ massa }} KG</p>
<p>Altura: {{ altura }} metros</p>
<p v-if="imc" :class="{'text-warning': imc > 30}">IMC: {{ imc }}</p>
<p v-else>Preencha os dados corretamene!</p>
</div>
</template>
O resultado caso o IMC seja maior que 30 será como mostrado na imagem abaixo.
binding de estilo
Outra forma de ter um resultado semelhante ao do tópico anterior é utilizando o binding
de estilo.
Nesse caso adicionaremos a propriedade css
color
com o valor red
caso o IMC seja maior que 30, essa alteração será
realizada no arquivo CalculadoraIMC.vue
.
<template>
<div>
<h1>Cálculo IMC</h1>
<div class="mb-3">
<label class="form-label">Massa em KG:</label>
<input v-model="massa" class="form-control" type="number">
</div>
<div class="mb-3">
<label class="form-label">Altura em metros:</label>
<input v-model="altura" class="form-control" type="number">
</div>
<p>Massa: {{ massa }} KG</p>
<p>Altura: {{ altura }} metros</p>
<p v-if="imc" :style="{'color': imc > 30 ? 'red' : 'black'}">IMC: {{ imc }}</p>
<p v-else>Preencha os dados corretamene!</p>
</div>
</template>
O resultado caso o IMC seja acima de 30 ficará como mostrado na imagem abaixo.