Esse manual foi feito por mim com base no curso da Udemy:
Curso completo da udemy. š
- Hello World
- Usando FunĆ§Ć£o
- Entendendo o this
- Diretiva v-bind
- Diretiva v-on
- Diretiva v-html
- Diretiva v-click
- Diretiva v-mousemove
- ParĆ¢metro Event
- Controlar teclas digitadas pelo usuƔrio (v-on:keyup)
- Eventos com Input
- InterpolaĆ§Ć£o
- Two-way-binding (v-model)
- Propriedades computadas
- Propriedade watch
- Sintaxe reduzida
- Estilo DinĆ¢mico e classes CSS
- Estilo DinĆ¢mico e classes CSS 2
- Estilo DinĆ¢mico e classes CSS 3
- Estilo DinĆ¢mico sem classe
- Condicional: v-if e v-else
- Condicional: v-else-if
- Condicional: v-else-if com Template
- Diretiva v-show
- Renderizando Lista com v-for
- Acesso ao Ćndice atual da lista
- Usando v-for com template
- Iterando em Objetos
- Identificando os Elementos no v-for (key)
- Iterando em uma Lista de NĆŗmeros
- Usando MĆŗltiplas InstĆ¢ncias Vue
- Acessando a InstĆ¢ncia Vue Externamente
- Como o VueJS Gerencia os Dados e MĆ©todos
- Montando um Template
- Usando Componentess
- O Ciclo de Vida da InstĆ¢ncia Vue
- Instalando o Node.JS
- Por que Precisamos de um Servidor Web?
- Instalando o Vue CLI e Criando um Novo Projeto
- Entendendo os Arquivos ".vue"
- Como Construir sua APP para ProduĆ§Ć£o
- Criando Preset
- Adicionando Plugin electron (para rodar a aplicaĆ§Ć£o no desktop)
- Criando um componente
- DeclaraĆ§Ć£o de componentes
- Usando CSS com Escopo de Componente(scoped)
- Nomes para componentes
- ComunicaĆ§Ć£o direta com props
- Validando propriedades
- ComunicaĆ§Ć£o Indireta com Eventos Personalizados
- ComunicaĆ§Ć£o Indireta com Callback
- ComunicaĆ§Ć£o entre componentes irmĆ£os
- Usando Event Bus para ComunicaĆ§Ć£o entre Componentes IrmĆ£ā¦
- Passando ConteĆŗdo com Slots
- Como o ConteĆŗdo do Slot Ć© Estilizado
- Usando MĆŗltiplos Slots (Slots Nomeados)
- Componentes dinĆ¢micos
- Mantendo o Componente DinĆ¢mico Vivo
- MĆ©todos de Ciclo de Vida de um Componente DinĆ¢mico
- Modificar Entrada de UsuƔrio com Modificadores de Input: lazy, string e number
- Usando <textarea> e Salvando Quebras de Linha
- Usando Checkboxes e Salvando os Dados em um Array
- Usando radio
- Manipulando Combobox com select e option
- Previnindo comportamento padrĆ£o do botĆ£o (prevent)
- Algumas diretivas
- Criando diretiva simples
- Passando valor para a diretiva personalizada
- Passando Argumento para diretiva personalizada
- Diretivas personalizadas com modificadores
- Anotomia de uma diretiva
- Registrar diretivas localmente
- Usando MĆŗltiplos Modificadores
- Passando Valores mais Complexos para as Diretivas
- Criando um filtro local
- Filtro Global e Como Encadear MĆŗltiplos Filtros
- Filtro com v-bind
- Usando mixins
- Bootstrap com Vue
- Dist Bootstrap
- Criando TransiĆ§Ć£o "Fade" com Propriedade CSS transition
- Criando TransiĆ§Ć£o "Slide" com Propriedade CSS animation
- Misturando as Propriedades transition e animation
- Tempo de animaĆ§Ć£o diferente de tempo de transiĆ§Ć£o
- Configurando AnimaĆ§Ć£o no Carregamento do Componente
- AnimaƧƵes com Animate.css
- Usando Nomes e Atributos DinĆ¢micos
- Transicionar entre MĆŗltiplos Elementos
- Usando transition-group (Para animar vƔrios elementos)
- Usando transition-group (Para animar vƔrios elementos)
Uma forma de usar o Vue, Ć© copiando a tag script da documentaĆ§Ć£o e colando no seu documento.
Dentro das tags HTML existe um conteĆŗdo de texto, as chaves duplas {{ }} funcionam como interpolaĆ§Ć£o do texto com o atributo do Vue.
Instanciando uma nova Vue new Vue() com o construtor.
O atributo el do Vue, representa qual trecho do HTML vou manipular passando o ID.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<p>{{ titulo }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
titulo: 'Hello World!'
}
})
</script>
Uma propriedade methods na instĆ¢ncia do Vue serve para adicionar minhas funƧƵes (ou mĆ©todos), repare que em data eu abro um objeto, a mesma coisa em methods
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<p>{{ titulo }}</p>
<p>{{ saudacao() }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
titulo: 'Usando VueJs!'
},
methods: {
saudacao: function(){
return 'Boa semana'
}
}
})
</script>
Repare que nĆ£o preciso usar {{ Vue.methods.saudacao }} e tambĆ©m {{ Vue.data.titulo }} , o Vue joga todas as propriedades para a raiz dele, e o this referencia o Vue, ou seja, pelo this consigo acesso direto as propriedades
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<p>{{ titulo }}</p>
<p>{{ saudacao() }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
titulo: 'Usando VueJs!'
},
methods: {
saudacao: function(){
console.log(this)
return this.titulo
}
}
})
</script>
O HTML permite que eu crie propriedades personalizadas, o Vue usou isso para criar as suas prĆ³prias e chamou isso de diretivas, ex: v-bind, v-model, etc.
Para usar os atributos do Vue nas propriedades, nĆ£o posso fazer assim
<a v-href="{{link}}">Google</a>
, as chaves sĆ³ funcionam pois dentro das tags do HTML eu tenho conteĆŗdo de texto e elas fazem entĆ£o a interpolaĆ§Ć£o, agora para as propriedades, tem que utilizar as diretivas do Vue, ex:<a v-bind:href="link">Google</a>
O v-bind faz uma ligaĆ§Ć£o do atributo link do Vue para o HTML.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<a v-bind:href="link">Google</a>
</div>
<script>
new Vue({
el: '#app',
data: {
link: 'http://google.com.br'
},
})
</script>
v-on esperando um evento acontecer para chamar uma funĆ§Ć£o.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<input v-on:input="saudacao">{{ titulo }}</input>
</div>
<script>
new Vue({
el: '#app',
data: {
titulo: 'Usando VueJs!',
},
methods: {
saudacao: function(){
this.titulo = "Mudei o texto"
return this.titulo
}
}
})
</script>
v-html Posso passar cĆ³digo HTML atravĆ©s de um atributo no Vue.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<p v-html="linkHtml"></p>
</div>
<script>
new Vue({
el: '#app',
data: {
linkHtml: '<a href="http://google.com.br">Google</a>'
}
})
</script>
v-on:click Ao ser clicado o elemento dispara uma funĆ§Ć£o.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<p>{{ contador }}</p>
<button v-on:click="somar">Somar 1</button>
</div>
<script>
new Vue({
el: '#app',
data: {
contador: 0
},
methods: {
somar(){
this.contador++
}
}
})
</script>
v-on:mousemove Ao passar o mouse em cima da tag
<p>
, Ć© mostrado a posiĆ§Ć£o do mouse.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<p>{{ contador }}</p>
<button v-on:click="somar">Somar 1</button>
<p v-on:mousemove="atualizarXY"> Mouse: {{x}} e {{y}}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
contador: 0,
x: 0,
y: 0
},
methods: {
somar(){
this.contador++
},
atualizarXY(event){
console.log(event)
this.x = event.clientX
this.y = event.clientY
}
}
})
</script>
Por padrĆ£o o Vue jĆ” reconhece o parĆ¢metro event, posso usar sem passar nada na funĆ§Ć£o
<button v-on:click="somar"
mas se eu passar outro parĆ¢metro para a funĆ§Ć£o e ainda sim quiser usar o evento, eu preciso usar o event assim$event
com dĆ³lar na frente e o nome obrigatoriamente precisa ser event.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<p>{{ contador }}</p>
<button v-on:click="somar(5, $event)">Somar 1</button>
</div>
<script>
new Vue({
el: '#app',
data: {
contador: 0,
},
methods: {
somar(passo, ev){
console.log(passo, ev)
this.contador += passo
},
}
})
</script>
Fica muito mais fƔcil controlar quais teclas o usuƔrio digitou, basta passar o nome da tecla v-on:keyup.(nome da tecla). Para controlar duas teclas pressionadas juntas v-on:keyp.(nomedatecla).(nomedatecla)
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<div>
<label>Ativa apĆ³s qualquer tecla:</label>
<input type="text" v-on:keyup="solteiTecla">
</div>
<div>
<label>Ativa apĆ³s o enter:</label>
<input type="text" v-on:keyup.enter="solteiEnter">
</div>
<div>
<label>Ativa apĆ³s o enter + alt:</label>
<input type="text" v-on:keyup.enter.alt="solteiEnter_Alt">
</div>
</div>
<script>
new Vue({
el: '#app',
methods: {
solteiTecla(){
alert('apertei qualquer tecla')
},
solteiEnter(){
alert('Apertei Enter')
},
solteiEnter_Alt(){
alert('Apertei enter+alt')
}
}
})
</script>
<input type="text" onkeypress="alteraTitulo(event)">
<p id="title">Curso Vue</p>
<script>
let p = document.querySelector("#title");
function alteraTitulo(event){
p.innerText = event.target.value;
}
</script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<input type="text" v-on:input="alteraTitulo">
<p>{{ title }}</p>
</div>
<script>
new Vue({
el: "#app",
data: {
title: "Curso Vue"
},
methods: {
alteraTitulo(event){
this.title = event.target.value;
}
}
})
</script>
Consigo escrever instruƧƵes simples de uma linha dentro das chaves duplas {{}}
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<p>{{ c }}</p>
<p>{{ c >= 10 ? "Ć maior ou igual a 10" : "Ć menor e diferente de 10"}}</p>
<p>Dobro do contador: {{ c * 2}}</p>
<button v-on:click="contador">Aumenta 1</button>
</div>
<script>
new Vue({
el: '#app',
data: {
c: 0
},
methods: {
contador(){
this.c++
}
}
})
</script>
Por enquanto com v-bind os dados da minha instĆ¢ncia Vue modificam apenas o template.
JĆ” os eventos ouvem no template e modificam apenas os dados da instĆ¢ncia Vue que por sua vez modificam o template.
Agora o v-model vai modificar ao mesmo tempo o template e os dados da minha instĆ¢ncia Vue, funcionando como um espelho ou uma via de mĆ£o dupla.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<input type="text" v-model="titulo">
<p>{{ titulo }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
titulo: 'Vue Js'
}
})
</script>
Quando existe alguma alteraĆ§Ć£o na irteface os componentes sĆ£o rendererizados novamente, entĆ£o os mĆ©todos sĆ£o invocados mesmo sem ter ligaĆ§Ć£o com as propriedades alteradas. Existe uma propriedade no vue chamada computed que o mĆ©todo sĆ³ vai ser invocado quando a propriedade que tem relaĆ§Ć£o com ele Ć© alterada.
Propriedades computed sĆ£o chamadas sem os pareteses ()
Repare que sem o computed, o mĆ©todo resultado() era chamado quando clicado em aumentar2, mesmo sem aumentar2 ter relaĆ§Ć£o nenhuma com o mĆ©todo resultado, com o computed uma propriedade computada serĆ” apenas invocada quando uma propriedade que estĆ” relacionada a ela Ć© atualizada!
O computed Ć© usado quando quero juntar dos dados em um sĆ³.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<button v-on:click="aumentar">Aumentar</button>
<button v-on:click="contador2++">Aumentar2</button>
<button v-on:click="diminuir">Diminuir</button>
<p>Contador: {{ contador1 }} | {{ contador2 }}</p>
<p>Resultado: {{ resultado }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
contador1: 0,
contador2: 0
},
computed: {
resultado(){
console.log("Ć chamado apenas quando modifico contador1")
return this.contador1 >= 5 ?
"maior ou igual a 5" : "menor que 5"
}
},
methods: {
aumentar(){
this.contador1++
},
diminuir(){
this.contador1--
},
/*
resultado(){
console.log(Ć chamado quando modifico contador 2, mesmo sem ter relaĆ§Ć£o)
return this.contador >= 5 ?
"maior ou igual a 5" : "menor que 5"
} */
}
})
</script>
Monitora a mudanƧa da propriedade.
Precisa ter o mesmo nome das propriedades dos dados.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<button v-on:click="aumentar">Aumentar</button>
<p>{{ contador }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
contador: 0,
},
watch: {
contador(novo, antigo){
console.log(novo, antigo)
}
},
methods: {
aumentar(){
this.contador++
}
}
})
</script>
eventos v-on podem ser substituĆdos por @ e o v-bind por :(dois pontos)
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<p>{{ contador }}</p>
<button @click="somar">Somar 1</button>
<hr>
<input type="text" :value="contador">
</div>
<script>
new Vue({
el: '#app',
data: {
contador: 0
},
methods: {
somar(){
this.contador++
}
}
})
</script>
Consigo Aplicar estilo CSS diretamente no template usando :class="{ (nome da classe): (valor booleano)}" ex: :class="{c1: true}
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
#app{
display: flex;
justify-content: space-around;
}
.demo{
width: 100px;
height: 100px;
background-color: gray;
}
.c1 {
background-color: red;
}
.c2 {
background-color: green;
}
.c3 {
background-color: blue;
}
</style>
<div id="app">
<div class="demo" :class="{c1: aplicarC1}"
@click="aplicarC1 = !aplicarC1"></div>
<div class="demo"></div>
<div class="demo"></div>
</div>
<script>
new Vue({
el: '#app',
data: {
aplicarC1: false
}
})
</script>
Uma outra forma de aplicar as classes css Ʃ usando a propriedade computed, consigo assim aplicar vƔrias classes de uma forma mais enxuta.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
#app{
display: flex;
justify-content: space-around;
}
.demo{
width: 100px;
height: 100px;
background-color: gray;
}
.c1 {
background-color: red;
}
.c2 {
background-color: green;
}
.c3 {
background-color: blue;
}
</style>
<div id="app">
<div class="demo" :class="estilo" @click="aplicarC1 = !aplicarC1"></div>
<div class="demo"></div>
<div class="demo"></div>
</div>
<script>
new Vue({
el: '#app',
data: {
aplicarC1: false
},
computed: {
estilo(){
return {
c1: this.aplicarC1,
c2: !this.aplicarC1
}
}
}
})
</script>
Mudar o nome da classe CSS atravƩs de propriedades do VUE
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
.caixas{
display: flex;
justify-content: space-around;
}
.demo{
width: 100px;
height: 100px;
background-color: gray;
}
.c1 {
background-color: red;
}
.c2 {
background-color: green;
}
.c3 {
background-color: blue;
}
.girar {
transform: rotate(45deg);
}
</style>
<div id="app">
<div class="caixas">
<div class="demo" :class="estilo" @click="aplicarC1 = !aplicarC1"></div>
<div class="demo"></div>
<div class="demo" :class="[classeCSS]"></div>
</div>
<hr>
<input type="text" v-model="classeCSS">
</div>
<script>
new Vue({
el: '#app',
data: {
aplicarC1: false,
classeCSS: "c1",
teste: "girar"
},
computed: {
estilo(){
return {
c1: this.aplicarC1,
c2: !this.aplicarC1
}
}
}
})
</script>
Lembrando que para aplicar o nome de uma classe no template que tenha - (hĆfe) preciso usar aspas. ex: 'background-color'
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
.caixas{
display: flex;
justify-content: space-around;
}
.demo{
width: 100px;
height: 100px;
background-color: gray;
}
</style>
<div id="app">
<div class="caixas">
<div class="demo" :style="{'background-color' : cor}"></div>
<div class="demo" :style="[meuEstilo, {height: altura} ]"></div>
<div class="demo"></div>
</div>
<hr>
<input type="text" v-model="cor">
<input type="text" v-model="largura">
</div>
<script>
new Vue({
el: '#app',
data: {
cor: 'red',
largura : '300',
altura : 20
},
computed: {
meuEstilo(){
return{
backGroundColor: this.cor,
width : this.largura + 'px'
}
}
}
})
</script>
v-if se a condiĆ§Ć£o for true aparece o elemento, se nĆ£o (v-else) aparece o outro elemento.
Veja nos elementos, eles desaparecem na DOM conforme a condiĆ§Ć£o.
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<p v-if="logado">UsuƔrio Logado: {{ nome }}</p>
<p v-else>Nenhum usuƔrio logado</p>
<button @click="logado = !logado">{{ logado ? 'Sair' : 'Entrar' }}</button>
</div>
<script>
new Vue({
el: '#app',
data: {
nome: 'Maria',
logado: false
}
})
</script>
Construir vƔrios if aninhados.
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<p v-if="logado">UsuƔrio Logado: {{ nome }}</p>
<p v-else-if="anonimo">Navegando como anƓnimo</p>
<p v-else>Nenhum usuƔrio logado</p>
<button @click="logado = !logado">{{ logado ? 'Sair' : 'Entrar' }}</button>
<input type="checkbox" v-model="anonimo">
</div>
<script>
new Vue({
el: '#app',
data: {
nome: 'Maria',
logado: false,
anonimo: false
}
})
</script>
Com a tag template do html 5, conseguimos envolver nossas tags sem o template aparecer na DOM.
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<template v-if="logado">
<p>UsuƔrio Logado: {{ nome }}</p>
<p>Perfil: admin</p>
</template>
<p v-else-if="anonimo">Navegando como anƓnimo</p>
<p v-else>Nenhum usuƔrio logado</p>
<button @click="logado = !logado">{{ logado ? 'Sair' : 'Entrar' }}</button>
<input type="checkbox" v-model="anonimo">
</div>
<script>
new Vue({
el: '#app',
data: {
nome: 'Maria',
logado: false,
anonimo: false
}
})
</script>
Com a diretiva v-show, o elemento nĆ£o desaparece da DOM, apenas Ć© usado um estilo para ele ficar display:none. v-show nĆ£o tem "else", basta aplicar uma negaĆ§Ć£o a ele. Como Ć© aplicado apenas um estilo, o v-show Ć© mais performĆ”tico do que o v-if, pois o v-if altera a DOM.
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<template v-if="logado">
<p>UsuƔrio Logado: {{ nome }}</p>
<p>Perfil: admin</p>
</template>
<p v-else-if="anonimo">Navegando como anƓnimo</p>
<p v-else>Nenhum usuƔrio logado</p>
<button @click="logado = !logado">{{ logado ? 'Sair' : 'Entrar' }}</button>
<input type="checkbox" v-model="anonimo">
<hr>
<footer v-show="logado">
Feito para vocĆŖ! {{ nome }}
</footer>
<footer v-show="!logado">
Feito para vocĆŖ desconhecido
</footer>
</div>
<script>
new Vue({
el: '#app',
data: {
nome: 'Maria',
logado: false,
anonimo: false
}
})
</script>
Com v-for eu consigo fazer algo semelhante ao for each
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<ul>
<li v-for="cor in cores">{{ cor }}</li>
</ul>
</div>
<script>
new Vue({
el: '#app',
data: {
cores: ['azul', 'verde', 'amarelo', 'rosa']
}
})
</script>
O segundo parĆ¢metro sempre serĆ” o segundo valor mais importante, nesse caso o Ćndice. **v-for="(cor, indice) in cores" **
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<ul>
<li v-for="(cor, indice) in cores">{{ indice }} - {{ cor }}</li>
</ul>
</div>
<script>
new Vue({
el: '#app',
data: {
cores: ['azul', 'verde', 'amarelo', 'rosa']
}
})
</script>
<style>
ul{
list-style-type: none;
}
</style>
tag template sempre ficarĆ” oculta na DOM.
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<ul>
<li v-for="(cor, indice) in cores">{{ indice }} - {{ cor }}</li>
</ul>
<hr>
<template v-for="(cor, indice) in cores">
<h1>{{ cor }}</h1>
<p>{{ indice }}</p>
</template>
</div>
<script>
new Vue({
el: '#app',
data: {
cores: ['azul', 'verde', 'amarelo', 'rosa']
}
})
</script>
<style>
ul{
list-style-type: none;
}
</style>
Nesse caso, o segundo parĆ¢metro de maior importante serĆ” a chave, e o terceiro o Ćndice.
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<ul>
<li v-for="pessoa in pessoas">
<span v-for="(valor, chave, index) in pessoa">
{{ chave }} = {{ valor }} ({{index}})
</span>
</li>
</ul>
</div>
<script>
new Vue({
el: '#app',
data: {
cores: ['azul', 'verde', 'amarelo', 'rosa'],
pessoas: [
{nome: 'Ana', idade: 26, peso: 59},
{nome: 'Guilherme', idade: 22, peso: 89}
]
}
})
</script>
<style>
ul{
list-style-type: none;
}
</style>
o atributo key Ʃ apenas um atributo que visa auxiliar o Vue no controle de alteraƧƵes em listas. Para que o que estƔ sendo apresentado na tela, reflita exatamente o que estƔ no array.
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<ul>
<li v-for="cor in cores" :key="cor">{{ cor }}</li>
</ul>
<input type="text" v-model="cor">
<button @click="cores.push(cor)">Adicionar</button>
</div>
<script>
new Vue({
el: '#app',
data: {
cor: '',
cores: ['amarelo', 'verde', 'azul', 'roxo', 'vermelho']
}
})
</script>
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<ul>
<li v-for="numero in 20">{{numero}}</li>
</ul>
</div>
<script>
new Vue({
el: '#app',
})
</script>
NĆ£o Ć© usual usar mĆŗltiplas instĆ¢ncias vue, mas esse capĆtulo Ć© para mostrar que isso Ć© possĆvel
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app1">
{{titulo1}}
<button @click="alterar">Alterar</button>
</div>
<div id="app2">
{{titulo2}}
<button @click="alterar">Alterar</button>
</div>
<script>
new Vue({
el: '#app1',
data: {
titulo1: 'teste1'
},
methods: {
alterar(){
this.titulo1 += '!!!'
}
}
})
new Vue({
el: '#app2',
data: {
titulo2: 'teste2'
},
methods: {
alterar(){
this.titulo2 += '!!!'
}
}
})
</script>
Consigo acessar dados de uma instĆ¢ncia Vue dentro de outra e acessar dados da Vue atravĆ©s de javascript puro.
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app1">
{{titulo1}}
<button @click="alterar">Alterar</button>
</div>
<div id="app2">
{{titulo2}}
<button @click="alterar">Alterar</button>
</div>
<script>
const vm1 = new Vue({
el: '#app1',
data: {
titulo1: 'teste1'
},
methods: {
alterar(){
vm2.titulo2 += '???'
}
}
})
const vm2 = new Vue({
el: '#app2',
data: {
titulo2: 'teste2'
},
methods: {
alterar(){
vm1.titulo1 += '!!!'
}
}
})
setTimeout(() => {
vm1.titulo1 = 'Alterado pelo timer'
}, 2000)
</script>
Consigo acessar dados de uma instĆ¢ncia Vue dentro de outra e acessar dados da Vue atravĆ©s de javascript puro.
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app1">
{{titulo1}}
<button @click="alterar">Alterar</button>
</div>
<div id="app2">
{{titulo2}}
<button @click="alterar">Alterar</button>
</div>
<script>
const vm1 = new Vue({
el: '#app1',
data: {
titulo1: 'teste1'
},
methods: {
alterar(){
vm2.titulo2 += '???'
}
}
})
const vm2 = new Vue({
el: '#app2',
data: {
titulo2: 'teste2'
},
methods: {
alterar(){
vm1.titulo1 += '!!!'
}
}
})
setTimeout(() => {
vm1.titulo1 = 'Alterado pelo timer'
}, 2000)
</script>
Aqui, estou adicionando uma nova propriedade para minha instĆ¢ncia vm.novainfo porĆ©m quando vou renderizar na tela, acontece o erro, esse dado nĆ£o Ć© reativo, pois nĆ£o declarei ele dentro da minha instĆ¢ncia Vue.
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
{{titulo}} {{ novaInfo}}
<button @click="alterar">Alterar</button>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
titulo: 'teste'
},
methods: {
alterar(){
this.titulo += '???'
}
}
})
vm.novaInfo = 'Teste'
console.log(vm.novaInfo)
</script>
Template aqui Ć© uma propriedade da instĆ¢ncia Vue, uso crases
para conseguir escrever em mais de uma linha. O template pode ser montado com o mĆ©todo $mount(#app) passando o #app ou com javascript puro como mostrando na Ćŗltima linha
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
</div>
<script>
const vm = new Vue({
template: `
<div>
<h1>{{ aula }}</h1>
<h2>{{ modulo }}</h2>
<button @click="alterarAula">Alterar Aula</button>
<button @click="alterarModulo">Alterar MĆ³dulo</button>
</div>
`
,
data:{
aula: 'Aula: montando instĆ¢ncia vue',
modulo: 'Modulo: InstĆ¢ncia Vue'
},
methods: {
alterarAula(){
this.aula += '#'
},
alterarModulo(){
this.modulo += '#'
}
}
})
//vm.$mount('#app')
vm.$mount()
document.querySelector('#app').appendChild(vm.$el)
</script>
Essa nĆ£o Ć© a melhor forma de usar componentes.
Repare que o data Ć© usado como funĆ§Ć£o, para que cada componentes tenha suas prĆ³prias propriedades, se fosse passado como na instĆ¢ncia, todo componentes teriam os mesmo dados alterados. Com a funĆ§Ć£o ele sempre retorna um diferente.
Componentes sĆ£o usados como tags HTML.
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<comp></comp>
<comp></comp>
<comp></comp>
</div>
<script>
Vue.component('comp', {
template: `
<div>
<h1>{{ aula }}</h1>
<h2>{{ modulo }}</h2>
<button @click="alterarAula">Alterar Aula</button>
<button @click="alterarModulo">Alterar MĆ³dulo</button>
</div>
`
,
data: function(){
return{
aula: 'Aula: montando instĆ¢ncia vue',
modulo: 'Modulo: InstĆ¢ncia Vue'
}
},
methods: {
alterarAula(){
this.aula += '#'
},
alterarModulo(){
this.modulo += '#'
}
}
})
const vm = new Vue({
el: '#app',
})
</script>
Todo o ciclo de como Ć© feito a instĆ¢ncia.
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<h1>{{ titulo }}</h1>
<button @click="titulo += '#'">Alterar Titulo</button>
<button @click="$destroy()">Destruir</button>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
titulo: 'Ciclo de vida'
},
beforeCreate() {
console.log('Antes de criar')
},
created(){
console.log('Criado')
},
beforeMount() {
console.log('Antes de montar! (DOM)')
},
mounted() {
console.log('DOM montada')
},
beforeUpdate() {
console.log('Antes de atualizar')
},
update(){
console.log('Atualizado')
},
beforeDestroy() {
console.log('Antes de destruir')
},
destroyed() {
console.log('Destruido')
},
})
</script>
Para esse capĆtulo precisamos usar o node.js.
Vamos usar tambƩm o NPM, que Ʃ um gerenciador de pacotes para node.js.
Instale o plugin vetur no vs code.
Baixe a versĆ£o LTS do node, que Ć© mais estĆ”vel.
Apesar de que o vue.js executa no client (se abrirmos o arquivo, estamos simulando o que o usuĆ”rio vai ver), esse arquivo foi servido atravĆ©s de um protocĆ³lo HTTP (servidor).
O protocĆ³lo HTTP nĆ£o tem as mesmas funcionalidades do que um protocĆ³lo do tipo File ( que Ć© quando abrimos o arquivo na nossa mĆ”quina).
Logo, o servidor Ć© importante para testarmos a aplicaĆ§Ć£o em cenĆ”rios mais realistas ( RequisiƧƵes Ajax precisam de um servidor).
O prĆ³prio Vue CLI internamente tem um servidor baseado em node, todo configurado, com auto reload e etc.
Vue CLI te da toda a estrutura do projeto, configuraƧƵes do projeto, build para desenvolvimento (que inicia um servidor), build de produĆ§Ć£o, etc.
Para instalar o vue CLI na sua mƔquina usando NPM, use o comando:
npm i -g @vue/cli
Agora o comando "vue" estĆ” disponĆvel. Para criar um novo projeto, basta usar o comando:
vue create (nomeprojeto)
Agora use os comandos indicados para entrar na pasta (cd) e para iniciar um servidor:
npm run serve
Repare que o arquivo App.vue tem 3 secƧƵes: template, script e style. FaƧa um teste apagando tudo e escreva "olĆ” mundo" no template, dentro de uma div. Na parte do script, vamos ter as mesmas propriedades da instĆ¢ncia Vue, faƧa um teste com data, mas lembre-se que por ser um componente, data precisa ser usada como funĆ§Ć£o, para que seus dados nĆ£o sejam iguais para todos os componentes usados. Adicione um estilo tambĆ©m, pegando pelo id.
<template>
<div id="app">
{{ titulo }}
<button @click="titulo += '#'">Alterar</button>
</div>
</template>
<script>
export default {
data: function(){
return{
titulo: "Teste data usando Vue.JS"
}
}
}
</script>
<style>
#app{
background-color: chocolate;
color: #ffffff;
}
</style>
Repare que nĆ£o existe um arquivo app.js, esse arquivo javascript fica em memĆ³ria. Para gerar esses arquivos e as pastar de produĆ§Ć£o, precisamos usar o comando:
npm run build
Repare que gerou a pasta dist, agora teremos nosso arquivo html com uma Ćŗnica linha, para ser o mais pequeno possĆvel, agora sim temos os arquivos js gerados. Com o comando npm run build, tiramos o arquivo js da memĆ³ria e de fato colocamos no disco.
Quando executamos o comando vue create (nome) aparece a opĆ§Ć£o para escolher um preset (que sĆ£o plugins e configuraƧƵes jĆ” definidos). Escolha a opĆ§Ć£o para definir manualmente os plugins, agora com a tecla de espaƧo, marque algumas opƧƵes, por exemplo: PWA, router, Vuex, Css Pre-processors, depois tecle enter e siga esses passos: 2x. De um sim (Y). Sass/SCSS (with node-sass). P Primeira opĆ§Ć£o Primeira novamente. Package.json Salvar. Por fim escolha o nome do preset. Pronto, estĆ” criando um preset.
Agora, quando comeƧar um novo projeto, irĆ” aparecer o seu preset como opĆ§Ć£o, ele terĆ” tudo configurado como foi feito. O seu projeto terĆ” mais coisas dentro dele.
Entre em package.json, e veja nas devDependencies, alguns plugins oficiais, sabemos disso pois comeƧa com @vue/cli-plugin-babel, agora plugins criados por terceiros usam o prefixo vue-cli-plugin. Na nossa aplicaĆ§Ć£o vamos usar o plugin electron-builder, como o prefixo Ć© padrĆ£o, para adicionar ao projeto basta usar o nome do plugin sem o prefixo, use o comando:
vue add electron-builder
Esse plugin Ć© vai construir sua aplicaĆ§Ć£o para desktop. Use o comando criado dentro do package.json, que Ć©:
npm run electron:serve
Ele abrirĆ” sua aplicaĆ§Ć£o no desktop.
Para mais opƧƵes adicione tambƩm o plugin:
vue add vuetify
Depois de criado a aplicaĆ§Ć£o com vue create, vamos criar um componente Contador.vue dentro da pasta src.
<template>
<div class="contador">
<span>{{ contador }}</span>
<button @click="adicionar">+</button>
<button @click="subtrair">-</button>
</div>
</template>
<script>
export default {
data(){
return{
contador: 0
}
},
methods: {
adicionar(){
this.contador++
},
subtrair(){
this.contador--
}
}
}
</script>
<style>
.contador span{
border-bottom: 1px solid #CCC;
height: 30px;
padding: 5px 25px;
}
.contador button{
height: 30px;
width: 30px;
border-radius: 15px;
background-color: coral;
color: #fff;
margin-left: 10px;
outline: none;
}
</style>
Dentro do arquivo main.js vamos importar esse componente:
import Contador from './Contador.vue'
Depois declarar esse componente como global ( global: pode ser usado em qualquer template), passando o nome que serĆ” usado:
Vue.component('app-contador', Contador)
O arquivo main.js completo ficarĆ” assim:
import Vue from 'vue'
import App from './App.vue'
import Contador from './Contador.vue'
Vue.config.productionTip = false
Vue.component('app-contador', Contador)
new Vue({
render: h => h(App),
}).$mount('#app')
Como o arquivo App.vue sempre comeƧarĆ” a aplicaĆ§Ć£o, podemos colocar o componente nele como se fosse um elemento :
<template>
<div id="app">
<h1>Contadores</h1>
<app-contador />
<app-contador />
<app-contador />
</div>
</template>
<script>
export default {
}
</script>
DeclaraĆ§Ć£o global, qualquer template tem acesso:
Vue.component('app-contadores', Contadores)
DeclaraĆ§Ć£o local, apenas o componente que ele foi declarado tem acesso:
import Contador from './Contador.vue'
export default {
components: { 'app-contador' : Contador }
}
Quando definimos um estilo para o nosso componente, esse estilo vai valer para todos os elementos, exemplo:
<style>
div {
border: 1px solid red;
}
</style>
Esse estilo da div vai valer para todas os componentes do meu projeto. Para que o estilo fique somente para o componente especĆfico, Ć© preciso escrever scoped no style.
<style scoped>
div {
border: 1px solid red;
}
</style>
O estilo Ć© transmitido para o filho direto do componente, mas nĆ£o para o filho do filho, ou seja, ele nĆ£o vai se propagar indefinidamente! Veja em inspecionar elemento, que Ć© gerado uma propriedade no elemento, com um hash para identificar cada um deles, exemplo de como vai aparecer : data-v-6cbbf471 , isso Ć© o vue aplicando o estilo nos elementos. Para procurar os que sĆ£o afetados pelo estilo, basta escrever isso no console, por exemplo: document.querySelectorAll('div[data-v-6cbbf471]')
Lembrando que se for definr um nome com hĆfen, Ć© preciso usar aspas em volta, mas se exportar o componente usando camel case ou pascal case, posso simplesmente usar o hĆfen aonde a letra fica maĆscula. Ex:
<app-usuario-info />
import AppUsuarioInfo from './UsuarioInfo'
export default {
components: { AppUsuarioInfo }
}
Usando aspas em volta ficaria assim:
<app-usuario-info />
import AppUsuarioInfo from './UsuarioInfo'
export default {
components: { 'app-usuario-info' : AppUsuarioInfo }
}
Propriedades nas tags sĆ£o aceitas pelo HTML, por exemplo <div class=""teste> OlĆ” mundo , class Ć© uma propriedade, assim como id, charset, entre outras. Agora para passar uma propriedade de um componente para outro, posso criar propriedades personalizadas.
No componente pai, eu tenho dados como "nome" :
<template>
<div id="pai">
<h1>Eu sou o componente pai!</h1>
<app-filho />
</div>
</template>
<script>
import Filho from './Filho.vue'
export default {
components: { 'app-filho' : Filho},
data() {
return {
nome: "Joao"
}
}
}
</script>
Agora eu quero passar esse "nome" para o componente filho, uma forma de fazer isso, Ć© definindo no componente filho, a propriedade "props", que vai aceitar propriedades passadas pelo componente pai.
<template>
<div class="filho">
<h2>Eu sou o componente Filho!</h2>
<p>{{ nome }}</p>
</div>
</template>
<script>
export default {
props: ['nome']
}
</script>
<style scoped>
</style>
Agora, basta passar a propriedade na tag app-filho:
<template>
<div id="pai">
<h1>Eu sou o componente pai!</h1>
<app-filho :nome="nome"/>
</div>
</template>
<script>
import Filho from './Filho.vue'
export default {
components: { 'app-filho' : Filho},
data() {
return {
nome: "Maria"
}
}
}
</script>
<style>
#pai {
color: rgb(60, 60, 170)
}
</style>
Vamos supor que vocĆŖ tenha uma propriedade nome que serĆ” passada do componente pai para o filho, e no componente filho ela execute esse mĆ©todo:
this.nome.split('').reverse().join('')
Esse mĆ©todo vai inverter a ordem de nome. Agora imagine que em nome vocĆŖ passe um nĆŗmero, bolean, ou qualquer tipo que nĆ£o seja string, isso vai gerar um erro, uma forma de tratar esse erro Ć© especificar o tipo da propriedade a ser recebida:
props: {
nome: String
}
Dessa forma Ć© mais fĆ”cil encontrar o erro no console, eu especifico o tipo esperado, repare que o tipo tem letra maiĆŗscula. Posso tambĆ©m esperar mais de um tipo, dessa forma:
props: {
nome: [String, Array]
}
TambƩm posso abrir minha propriedade nome como se fosse um objeto, dessa forma:
props: {
nome: {
type: String,
require: true
}
}
To dizendo que o tipo Ć© String, Ć© obrigatĆ³rio que se passe a propriedade, usando o require: true TambĆ©m posso passar a propriedade default, quando nada for passado ele usarĆ” o que estiver em default:
props: {
nome: {
type: String,
default: 'joĆ£o'
}
}
Existe uma forma de passar o evento do componente filho para o componente pai, passando dentro da funĆ§Ć£o:
reiniciarNome(){
this.nome = "Pedro",
this.$emit('nomeMudou', this.nome)
}
Estou criando um evento chamado "nomeMudou", que estĆ” associado com a propriedade "nome". Agora Ć© sĆ³ "ouvir" esse evento, como se fosse um evento normal (@click ou qualquer outro).
<app-usuario-info :nome="nome" @nomeMudou="nome = $event"/>
Dentro do componente pai eu estou passando o evento. o $event, vai ter o valor do "this.nome". No caso estou alterando o valor da variƔvel nome, com o $event.
Posso tambƩm, passar um objeto no this.$emit :
reiniciarNome(){
const antigo = this.nome
this.nome = "Pedro",
this.$emit('nomeMudou', {
novo: this.nome,
antigo
})
}
Agora consigo acessar essas propriedades usando $event.novo ou $event.antigo
<div class="componentes">
<app-usuario-info
:nome="nome"
@nomeMudou="nome = $event.antigo + $event.novo "/>
<app-usuario-editar />
</div>
Outra forma de comunicaĆ§Ć£o entre filho e pai, Ć© ultilizar callbacks
<div class="componentes">
<app-usuario-info
:nome="nome"
:reiniciarFn="reiniciarNome"/>
<app-usuario-editar />
</div>
No componente pai, estou passando uma funĆ§Ć£o reiniciarNome pela propriedade ReiniciarFn
props: {
nome: {
type: String,
require: true
},
reiniciarFn: Function
},
Agora declaro a funĆ§Ć£o nas propriedades do componente filho, do tipo Function.
E posso chamar essa propriedade disparando um evento como o click:
<button @click="reiniciarFn">Reiniciar Nome (call back)</button>
NĆ£o existe comunicaĆ§Ć£o direta entre irmĆ£os. Uma forma de fazer, seria: o filho gera um evento para o pai, e o pai altera nĆ£o sĆ³ o filho que gerou o evento, mas tambĆ©m os outros filhos, se o pai tiver propriedades associadas aos filhos.
EntĆ£o: Filho1 altera o pai, e depois o pai altera o valor do filho1 e do filho2.
Posso criar dentro da pasta src um barramento.js, que irĆ” instanciar uma vue.
barramento.js
import Vue from 'vue'
export default new Vue()
No componente filho posso imitir alguma evento que causou alguma alteraĆ§Ć£o, usando o barramento:
import barramento from '@/barramento'
export default {
props: {
idade: Number
},
methods: {
alterarIdade(){
this.idade = 33
barramento.$emit('idadeMudou', this.idade)
}
}
}
Agora no componente irmĆ£o, eu posso ficar ouvindo se esse evento serĆ” disparada, e entĆ£o passar uma callbak pra ele executar:
import barramento from '@/barramento'
created(){
barramento.$on('idadeMudou', idade => {
this.idade = idade
})
}
Repare que estou usando a funĆ§Ć£o created() do vue, ela estĆ” fora da propriedade methods do componente filho. Pronto, agora os valores serĆ£o alterados apenas nos irmĆ£os.
Ć possĆvel passar conteĆŗdo pelo componente, dentro da tag filho. No componente pai (citacoes), passamos o conteĆŗdo assim dentro do componente filho(citacao):
<template>
<div class="citacoes">
<Citacao>
<h1>{{citacoes[indice].autor}}</h1>
<p>{{ citacoes[indice].texto }}</p>
<h6>{{ citacoes[indice].fonte }}</h6>
</Citacao>
</div>
</template>
Agora no componente citacao passamos apenas a tag slot
<template>
<div class="citacao">
<slot></slot>
</div>
</template>
O estilo Ć© passado tanto no componente que tem a tag slot, quanto no componente que passa o contĆ©udo, sendo que esse o que tem preferĆŖncia.
Posso tambƩm definir o estilo que quero usando !important
h1 {
color: red!important;
}
Consigo passar vƔrios slots, basta colocar a propriedade slot na tag que quero passar no componente pai (citacoes):
<Citacao>
<p slot="teste">OlĆ” eu estou aqui</p>
</Citacao>
Agora no componente filho, eu passo na tag slot, a propriedade name:
<template>
<div class="citacao">
<slot></slot>
<slot name="teste"></slot>
</div>
</template>
Existe um elemento personalizado do vue.js chamado component, que possuĆ a propriedade :is, aonde eu posso passar alguma propriedade (que corresponde a algum componente com aspas simples) e entĆ£o o vue irĆ” resolver para mim:
<component :is="componente"/>
E dai posso fazer o que eu quiser com a propriedade passada componente, nesse caso estou passando 'Citacoes':
export default {
components: { Citacoes, Sobre },
data(){
return {
componente: 'Citacoes'
}
}
}
Posso por exemplo criar dois botƵes, aonde o valor de componente serƔ alterado:
<template>
<div id="app">
<span>
<button @click="componente = 'Citacoes'">CitaƧƵes</button>
<button @click="componente = 'Sobre'">Sobre</button>
</span>
<component :is="component"/>
</div>
</template>
Toda vez que eu troco de um componente para outro, o componente trocado Ć© destruĆdo, posso observar isso usando os mĆ©todos de ciclo vida: created e destroyed, passando um console.log() para observar quando um ou outro Ć© ativado.
Mas sempre um componente Ć© destruĆdo, se eu quero mante-lo vivo, para que na volta ele mostre o mesmo resultado de antes, possa usar um elemento personalidado do vue, chamado keep-alive e envolver o meu componente:
<keep-alive>
<component :is="component"/>
</keep-alive>
Pronto, agora ele nĆ£o serĆ” mais destruĆdo.
Consigo observar quando um componente Ć© criado, destruĆdo, ativado ou desativo com esses mĆ©todos:
created(){
console.log('created')
},
destroyed(){
console.log('destroyed')
},
activated(){
console.log('ativo')
},
deactivated(){
console.log('desativado')
}
Lembrando que os mĆ©todos de ativar ou desativar, sĆ³ seram chamados se o elemento keep-alive estiver definido. ā¬ Voltar para o Ćndice
Com a diretiva v-model, cada tecla serĆ” refletida no dado, agora se vocĆŖ quiser que seja modificado apenas quando tirar o foco do campo, por exemplo clicar fora do campo "e-mail" Ć© sĆ³ usar v-model.lazy, ou seja, o v-model vai ficar com "preguiƧa" e sĆ³ modificar depois:
<label nome="E-mail">
<input type="text" v-model.lazy="usuario.email">
</label>
Temos tambƩm o trim que tira os espaƧos em branco no comeƧo e no fim do input
v-model.trim posso usar tambƩm como v.model.lazy.trim
O v-model.number transforma o valor de string para number, isso Ć© Ćŗtil pois sempre no input, o valor retornado Ć© uma string.
o v-model.number vai forƧar o valor do campo a ser nĆŗmero
Podemos usar o textarea com o v-model, o ruim Ć© que quando pulamos a linha, ou deixamos um espaƧo em branco, isso nĆ£o Ć© refletido. Para que os espaƧos em branco sejam preservados precismos usar o style: white-space: pre; -> "EspaƧos em branco preservados
<span>Mensagem com mĆŗltiplas linhas:</span>
<p style="white-space: pre;">{{ message }}</p>
<br>
<textarea v-model="message" placeholder="Escreva bastante"></textarea>
Com o checkbox armazenamos os dados selecionados dentro um array. O v-model vai pegar o que estĆ” em value.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<input type="checkbox" value="ativado" v-model="selecionados"> <label for="">ativado</label>
<input type="checkbox" value="desativado" v-model="selecionados"> <label for="">desativado</label>
<p>{{selecionados}}</p>
</div>
<script>
new Vue({
el: "#app",
data: {
selecionados: []
}
})
</script>
Com o v-model o radio vai selecionar apenas uma opĆ§Ć£o, basta colocar o v-model nos dois input radio. O valor do v-model Ć© pego pelo value tambĆ©m.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<input type="radio" value="one" v-model="picked"> <label for="">One</label>
<input type="radio" value="Two" v-model="picked"> <label for="">Two</label>
<p>Picked: {{picked}}</p>
</div>
<script>
new Vue({
el: "#app",
data: {
picked: ''
}
})
</script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<p>Personagem: </p>
<select v-model="selecionado">
<option v-for="personagem in personagens" :value="personagem.codigo"
>
{{personagem.nome}}
</option>
</select>
<p>Escolhido: {{selecionado}} </p>
</div>
<script>
new Vue({
el: "#app",
data: {
personagens: [
{codigo: 1, nome: "Home Lander"},
{codigo: 2, nome: "Trem Bala"},
{codigo: 3, nome: "Tempestade"}
],
selecionado: 3
}
})
</script>
Para que o botĆ£o nĆ£o faƧa o comportamento padrĆ£o de submit, Ć© preciso usar @click.prevent, assim ele vai se "prevenir" do comportamento padrĆ£o.
<p v-text="'Usando diretiva v-text'"></p>
<p v-html="'Usando diretiva <strong>v-html</strong>'"></p>
o mƩtodo bind Ʃ um mƩtodo hook, chamado apenas uma vez quando a diretiva Ʃ interligada com o elemento. "el" Ʃ o elemento que a diretiva estƔ vinculada, Ʃ usado para manipular a DOM diretamente
Vue.directive('destaque', {
bind(el){
el.style.backgroundColor = 'lightgreen';
}
})
Para usar a diretiva criada:
<p v-destaque>Usando minha diretiva</p>
Com o parĆ¢metro binding consigo passar valores para a minha diretiva, nesse caso, por ser uma cor, o valor precisa estar entre aspas simples dentro das aspas duplas e Ć© preciso atualizar a pĆ”gina tambĆ©m, o auto reload nĆ£o funciona muito bem aqui.
Vue.directive('destaque', {
bind(el, binding){
el.style.backgroundColor = binding.value;
}
})
Para usar a diretiva
<p v-destaque="'blue'">Usando minha diretiva</p>
Outro exemplo
<p v-destaque="1 + 1">Usando minha diretiva</p>
---------------------------------------------
Vue.directive('destaque', {
bind(el, binding){
el.innerText = binding.value;
}
})
Outro exemplo: Posso passar como dado normal
<p v-destaque="cor">Usando minha diretiva</p></div>
export default {
data(){
return {
cor: 'red'
}
}
}
O argumento da diretiva vem nos dois pontos :, igual quando temos v-bind:value, o argumento Ć© value, ou v-on:click, o argumento Ć© o click. EntĆ£o podemos pegar o argumento com binding.arg ( no singular, podemos ter apenas um Ćŗnico argumento) e verificar se ele existe ou nĆ£o:
Vue.directive('destaque', {
bind(el, binding){
if(binding.arg === 'fundo'){
el.style.backgroundColor = binding.value;
} else {
el.style.color = binding.value;
}
}
})
Se o argumento existir, ele vai aplicar o fundo, se nĆ£o vai aplicar apenas a cor. Para usar a diretiva criada com argumento:
<p v-destaque="'lightblue'">Usando minha diretiva</p>
Posso ter vĆ”rios modificadores, eu vejo se eles estĆ£o sendo passados com binding.modifiers['']
Vue.directive('destaque', {
bind(el, binding){
let atraso = 0;
if(binding.modifiers['atrasar']) atraso = 2000;
setTimeout(() => {
if(binding.arg === 'fundo'){
el.style.backgroundColor = binding.value;
} else {
el.style.color = binding.value;
}
}, atraso);
}
})
Para usar a diretiva criada com modificador:
<p v-destaque:fundo.atrasar="'lightblue'">Usando minha diretiva</p>
nome da diretiva:argumento.modificadores
v-diretiva:argumento.mod1.mod2.mod3....
export default {
directives:{
'destaque-local':{
bind(el, binding){
let atraso = 0;
if(binding.modifiers['atrasar']) atraso = 2000
setTimeout(() =>{
if(binding.arg === 'fundo'){
el.style.backgroundColor = binding.value;
} else {
el.style.color = binding.value;
}
}, atraso)
}
}
}
export default {
directives:{
'destaque-local':{
bind(el, binding){
const aplicarCor = cor => {
if(binding.arg === 'fundo'){
el.style.backgroundColor = cor;
} else {
el.style.color = cor;
}
}
let atraso = 0;
if(binding.modifiers['atrasar']) atraso = 2000
const cor1 = binding.value;
const cor2 = 'purple';
let corAtual = cor1;
setTimeout(() =>{
if(binding.modifiers['alternar']){
setInterval(()=>{
corAtual = corAtual === cor1 ? cor2 : cor1;
aplicarCor(corAtual);
}, 1000)
}
aplicarCor(binding.value)
}, atraso)
}
}
}
Chamando a diretiva:
Usando diretiva personalizada
Consigo passar os valores como objeto
<p v-destaque-local.atrasar.alternar="{cor1: 'green', cor2: 'red', atraso: 2000, intervalo: 200}">Usando diretiva personalizada</p>
Para ter acesso ao valor, basta usar o binding.value.(nomeDoAtributo). Ex: binding.value.cor1 que seria igual a green.
Filtro funciona como se fosse uma mĆ”scara para os inputs, entĆ£o para criar um filtro local na minha aplicaĆ§Ć£o posso passar como propriedade:
export default {
filters:{
cpf(valor){
const arr = valor.split('');
arr.splice(3, 0, '.');
arr.splice(7, 0, '.');
arr.splice(11, 0, '-');
return arr.join('');
}
},
}
E para aplicar esse filtro no seu dado, basta criar o dado normal na propriedade data, aqui vou criar chamado cpf tambƩm, e para aplicar o filtro basta usar o pipe:
<p>{{ cpf | cpf}}</p>
NĆ£o tem problema usar o mesmo nome, poderia usar outro, mas usar o mesmo o Vue entende que o primeiro Ć© o dado e o segundo Ć© o filtro.
Vue.filter('inverter', (valor)=>{
return valor.split('').reverse().join('');
});
Posso aplicar diversos filtro encadeados que serĆ£o aplicados no valor:
<p>{{ cpf | cpf | inverter }}</p>
Posso tambƩm passar o valor diretamente:
<p>{{ '728172817' | cpf | inverter }}</p>
Consigo aplicar o filtro com v-bind tambƩm:
<input type="text" :value="cpf | cpf | inverter">
});
Filtro nĆ£o suporta o v-model, filtros nĆ£o sĆ£o muito otimizados, mas Ć© bom para projetos simples, para ter mais otimizaĆ§Ć£o Ć© melhor usar as propriedades computas.
Com mixins eu consigo unir, "misturar" os dados do mixins com os dados de qualquer componente que eu queira usar, entĆ£o por exemplo, tenho esse mixin:
<script>
export default {
data(){
return{
fruta: '',
frutas: ['banana', 'maƧa', 'laranja']
}
},
methods:{
add(){
this.frutas.push(this.fruta)
this.fruta = ''
}
}
}
</script>
});
Agora consigo chamar esse mixins em qualquer lugar, que os dados do componente ficaram unidos com os dados do mixin, e os dados serĆ£o diferentes para componente, para declarar Ć© sĆ³ usar essa declaraĆ§Ć£o em qualquer componente:
export default {
mixins: [FrutasMixins]
}
Para usar boostrap no vue, posso adicionar o plugin dessa forma:
vue add bootstrap-vue
Para usar basta colocar b- (nome do elemento): obs: variant="primary" para cor azul
<b-button variant="primary" />
<b-alert variant="info" show></b-alert>
Posso criar uma basta dentro de src chamada plugins e lĆ” colocar um arquivo js "bootstrap-vue.js":
import Vue from 'vue'
import BootstrapVue from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.min.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
Vue.use(BootstrapVue)
Usando o v-if, o componente aparece e desaparece de forma abrupta, podemos fazer um efeito de transiĆ§Ć£o para que desapareƧa e apareƧa lentamente, usando a tag transition em volta do elemento que irĆ” desaparecer:
<transition name="fade">
<b-alert variant="info" show v-if="exibir">{{msg}}</b-alert>
</transition>
O nome fade Ć© opcional, posso usar qualquer nome. As classes que dĆ£o efeito de transiĆ§Ć£o sĆ£o as: (Aonde o asterisco significa que posso usar qualquer nome, nesse exemplo estou usando o nome "fade") 1. *-enter: enter de "entrar", o elemento vai "entrar" na tela, entĆ£o no inĆcio ele nĆ£o irĆ” aparecer, ou seja: opacity: 0. 2. *-enter-active: Ć o efeito que irĆ” acontecer no elmemento. Ex: transition: opacity 2s; 3. *-enter-to: Ć o efeito final, quando o elemento aparece: opacity: 1; 4. *-leave : leave Ć© sair, ou seja o elemento vai sair da tela, aqui o elemento comeƧa com opacity: 1; 5. *-leave-active: transiĆ§Ć£o parece ele sair. 6. *-leave-to: elemento sai de vez com opacity: 0;
Como a transiĆ§Ć£o jĆ” leva o opacity a 1, posso simplemente oculta-lo, e como alguns padrƵes se repetem, posso escrever dessa forma:
.fade-enter, .fade-leave-to{
opacity: 0;
}
.fade-enter-active, .fade-leave-active{
transition: opacity 2s;
}
@keyframes slide-in {
from { transform: translateY(40px); }
to { transform: translateY(0); }
}
@keyframes slide-out {
from { transform: translateY(0); }
to { transform: translateY(40px); }
}
.slide-enter-active {
animation: slide-in 2s ease;
}
.slide-leave-active {
animation: slide-out 2s ease;
}
</style>
<transition name="slide">
<b-alert variant="info" show v-if="exibir">{{msg}}</b-alert>
</transition>
@keyframes slide-in {
from { transform: translateY(40px); }
to { transform: translateY(0); }
}
@keyframes slide-out {
from { transform: translateY(0); }
to { transform: translateY(40px); }
}
.slide-enter-active {
animation: slide-in 2s ease;
transition: opacity 2s;
}
.slide-leave-active {
animation: slide-out 2s ease;
transition: opacity 2s;
}
.slide-enter, .slide-leave-to{
opacity: 0;
}
Image que a transiĆ§Ć£o tenha mais tempo do que a animaĆ§Ć£o:
.slide-leave-active {
animation: slide-out 2s ease;
transition: opacity 6s;
}
Isso gera um efeito estranho, para contornar isso, existe o atributo type que serve para dizer qual efeito vai ter prioridade:
<transition name="slide" type="animation">
Agora nĆ£o importa o tempo de transiĆ§Ć£o, como defini type="animation", apĆ³s ela terminar, irĆ” desaparecer o efeito. ā¬ Voltar para o Ćndice
Para que aconteƧa o efeito ao carregar a pƔgina, basta usar a propriedade appear:
O animate tem vƔrias animaƧƵes legais para serem utilizadas: animate
Para usar basta pegar o nome do lado direito e colocar animate na frente:
<transition
enter-active-class="animated swing"
leave-active-class="animated shake">
<b-alert variant="info" show v-if="exibir">{{msg}}</b-alert>
</transition>
E no arquivo index.html da pasta public usar o link:
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css" />
<b-select v-model="tipoAnimacao">
<option value="slide">Slide</option>
<option value="fade">Fade</option>
</b-select>
<transition :name="tipoAnimacao">
<b-alert variant="info" show v-if="exibir">{{msg}}</b-alert>
</transition>
Para eu conseguir trocar de elementos e mesmo assim o efeito continuar, preciso usar a propriedade key. E para que um elemento tenha seu efeito e sĆ³ depois entre outro elemento, tenho que usar mode= out-in.
<b-select v-model="tipoAnimacao">
<option value="slide">Slide</option>
<option value="fade">Fade</option>
</b-select>
<transition :name="tipoAnimacao" mode="out-in">
<b-alert variant="info" show v-if="exibir" key="info">{{msg}}</b-alert>
<b-alert variant="warning" show v-else key="warn">{{msg}}</b-alert>
</transition>
<template>
<div id="app" class="container-fluid">
<h1>AnimaƧƵes</h1>
<b-button @click="adicionarAluno" class="mb-4">Adicionar</b-button>
<transition-group name="slide">
<b-list-group v-for="(aluno,i) in alunos" :key="aluno">
<b-list-group-item @click="removerAluno(i)">
{{aluno}}
</b-list-group-item>
</b-list-group>
</transition-group>
</div>
</template>
<script>
export default {
data(){
return{
alunos: ['Paulo', 'JoĆ£o', 'Roberto', 'Pedro']
}
},
methods: {
adicionarAluno(){
let a = Math.random().toString(36).substring(2);
this.alunos.push(a)
},
removerAluno(indice){
this.alunos.splice(indice, 1);
}
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
font-size: 1.5rem;
}
.caixa{
height: 100px;
width: 300px;
margin: 30px auto;
background-color: lightgreen;
}
.fade-enter, .fade-leave-to{
opacity: 0;
}
.fade-enter-active, .fade-leave-active{
transition: opacity 2s;
}
@keyframes slide-in {
from { transform: translateY(40px); }
to { transform: translateY(0); }
}
@keyframes slide-out {
from { transform: translateY(0); }
to { transform: translateY(40px); }
}
.slide-enter-active {
position: absolute;
width: 100%;
animation: slide-out 2s ease;
animation: slide-in 2s ease;
transition: opacity 2s;
}
.slide-leave-active {
animation: slide-out 2s ease;
transition: opacity 2s;
}
.slide-enter, .slide-leave-to{
opacity: 0;
}
.slide-move{
transition: transform 1s;
}
</style>
Nesse capĆtulo estamos usando banco de dados do firebase. Para instalar o axios na sua aplicaĆ§Ć£o juto com a pasta node modules, execute esse comando:
npm i --save axios
Isso vai mostrar no arquivo package.json a versĆ£o do axios instalada.
Para executar o axios de forma global, dentro da plugins crie um arquivo axios.js e dentro coloque esse cĆ³digo:
import Vue from 'vue';
import axios from 'axios';
axios.defaults.baseURL = 'URL do seu banco de dados do firebase';
Vue.use({
install(Vue){
Vue.prototype.$http = axios
}
})
Agora basta importar no arquivo main.js:
import './plugins/axios'
npm i --save vue-router@3.0.2 -E
Flag -E Ć© para in
stalar exatamente essa versĆ£o. ā¬ Voltar para o Ćndice
Basta eu registrar as rotas num arquivo routes.js e importar qual componente irei usar em qual caminho:
import Vue from 'vue'
import Router from 'vue-router'
import Inicio from './components/Inicio.vue'
import Usuario from './components/usuario/Usuario.vue'
Vue.use(Router)
export default new Router({
routes: [{
path: '/',
component: Inicio
}, {
path: '/usuario',
component: Usuario
}]
})
Agora basta importar no arquivo main.js e colocar como propriedade do Vue:
import './style.css'
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
}).$mount('#app')
Agora para mostrar esses componentes pasta colocar a tag ā¬ Voltar para o Ćndice
O modo hash aparece um # na url, quando Ć© feito a requisiĆ§Ć£o, ela passa pelo index, o index direciona para o app (aonde estĆ” o vue), no caos da requesiĆ§Ć£o com #: http://localhost:8080/#/usuario O servidor sĆ³ recebe http://localhost:8080/ basta ver isso na aba network. E assim ele Ć© obrigado a passar pelo index, e o browser com # direciona para os componentes. O modo history vai fazer a requisiĆ§Ć£o na url diretamente no servidor, ficaria: (Na aba network Ć© possĆvel ver que a requisiĆ§Ć£o Ć© completa) http://localhost:8080/usuario Para mudar entre os dois modos, basta na minha instĆ¢ncia router adicionar a propriedade mode e fazer a escolha, ou hash ou history:
export default new Router({
mode: 'history',
routes: [{
path: '/',
component: Inicio
}, {
path: '/usuario',
component: Usuario
}]
})
O comportamento padrĆ£o do link Ć© trazer uma pĆ”gina html inteira, com o router-link, ele faz uma requisiĆ§Ć£o do tipo AJAX:
<template>
<nav class="menu">
<router-link to="/">InĆcio</router-link>
<router-link to="/usuario">UsuƔrio</router-link>
</nav>
</template>
<script>
export default {
}
</script>
<style>
</style>
Agora basta registrar esse componente e usar!
Para passar parĆ¢metros na url basta usar /:(nome do parĆ¢metro):
path: '/usuario/:id'
Agora para pegar o valor do parĆ¢metro passado:
this.$route.params.id
Quando existe mudanƧa para componentes do mesmo tipo, Ć© melhor usar a propriedade watch para monitorar a mudanƧa de $roue e aconteƧa a mudanƧa do parĆ¢metro:
watch:{
$route(to, from){
this.id = to.params.id
}
}
Existe uma forma mais simples que Ć© usando propriedade, no componente coloque props com o nome do parĆ¢metro passado na url e na instĆ¢ncia router, Defina props como true, pronto, agora nĆ£o precisa usar data e nem watch para monitor as mudanƧas dos parĆ¢metros:
export default new Router({
mode: 'history',
routes: [{
path: '/',
component: Inicio
}, {
path: '/usuario/:id',
component: Usuario,
props: true
}]
})
Configurando Rotas Filhas (Rotas Aninhadas)