slides.com/renanthompsom/vuejs
Introdução ao Vue.js
Ministrantes
O que é o Vue.js?
Vue (pronuncia-se /vjuː/, como view, em inglês) é um framework progressivo para a construção de interfaces de usuário.
Por que aprender
Vue.js?
Por que aprender Vue.js?
- Open Source;
- Acessível (HTML, CSS e JavaScript);
- Versátil;
- Performático;
- Escalável (reuso de componentes);
- Curva de aprendizado baixa;
- Fácil integração.
O criador - Evan You
Desenvolvimento do Vue - Linha do tempo
- 2013: Evan começa o Vue no seu tempo livre enquanto trabalhava no Google.
- 2015: Evan gasta todos os dias de suas férias para lançar a v1.0 em Outubro.
- 2016: Evan começa a trabalhar em tempo integral no Vue, financiado pelo Patreon.
- 2018: Evan contrata seus primeiros empregados para corrigir bugs.
Evan You - Patreon
Meme Generator
Meme Generator
Tópicos
- A instância Vue
- Ciclo de vida da instância Vue
- Dados computados
- Renderização condicional
- Interligações de atributos
- Interligações de formulários
- Manipulação de eventos
- Renderização de listas
- Interligações de classe e estilo
- Componentes
- Eventos customizados
- Desafios
Requisitos mínimos
- Conhecimentos básicos de HTML, CSS, e JavaScript.
- Experiência anterior com outros frameworks ajuda, mas não é necessária.
Vue.js devtools
componentes
Vue.js devtools
eventos
Vue.js devtools - links
Vue.js devtools - config
1. A Instância Vue
Nesse tópico, vamos aprender como usar o Vue para exibir dados em uma página web.
Objetivo
Vamos adicionar o título de nossa aplicação.
Código inicial
index.html
main.js
<!DOCTYPE html>
<html>
<head>
<title>Meme Generator</title>
</head>
<body>
<div id="app">
<h1>Meme Name</h1>
</div>
<script src="./assets/js/main.js"></script>
</body>
</html>
let meme = 'Dog Meme';
Problema
Nós precisamos de alguma forma mostrar o valor da variável meme dentro do <h1> no nosso html.
index.html
<script src="https://unpkg.com/vue"></script>
O primeiro passo é incluir o script do Vue no nosso projeto.
Solução
E assim usar a nossa primeira expressão JavaScript
index.html
main.js
E no nosso main.js, vamos incluir a instância do Vue
const app = new Vue({
el: '#app',
data: {
meme: 'Dog'
}
})
<div id="app">
<h1>{{ meme }}</h1>
</div>
Vamos ver o nome Dog dentro de nossa tag <h1>
Resultado
WTF?
A Instância Vue
A instância Vue é a raiz de nossa aplicação. Ela é criada passando um objeto com suas opções.
Nesse objeto tem uma variedade de propriedades opcionais que dão a instância a habilidade de armazenar dados e realizar ações.
const app = new Vue({options})
Conexão com um elemento
A instância Vue é então conectada com um elemento de sua escolha, formando um relacionamento entre a instância e uma parte do DOM (Document Object Model).
Em outras palavras, nós estamos ativando o Vue na div com o id app, colocando '#app', como o elemento (el) da nossa instância.
el: '#app'
DOM - Document Object Model
Propriedade 'data'
Uma instância do Vue possui a propriedade data para inserir os dados
Os dados da instância podem ser acessados dentro do elemento em que a instância está plugada.
data: {
meme: 'Dog'
}
<div id="app">
<h1>{{ meme }}</h1>
</div>
Usando a expressão {{ }}
Se nós queremos que algum dado seja mostrado no html, é preciso adicionar as chaves duplas entre o valor a ser exibido.
<h1>{{ meme }}</h1>
Termo importante: Expression
- Expressões permitem utilizar valores existentes de dados, em conjunto com lógica, para produzir novos valores de dados.
- Quando o Vue visualiza a expressão {{ meme }}, ele reconhece que nós estamos referenciando aos dados de sua instância, e ele substitui aquela expressão com o seu devido valor, no nosso caso o nome do meme que é: "Dog".
Expression
Expressões - outros exemplos
{{ title.toUpperCase() }}
{{ firstName + ' ' + lastName }}
{{ ok ? 'SIM' : 'NÃO' }}
Reatividade
- A razão do Vue ser capaz de mostrar o valor dos dados imediantamente é porque o Vue é reativo.
- Em outras palavras, os dados da instância estão interligados a cada local em que o dado está sendo referenciado.
Para provar isso, vamos abrir o console e alterar o valor de nossa string meme. Vamos ver o que acontece.
Reatividade
Busquem conhecimento!!
1. A instância Vue
- Como começar a escrever uma aplicação Vue utilizando sua instância;
- Como exibir dados em uma página web;
- A instância Vue é a raiz de toda aplicação Vue;
- A instância Vue é conectada com um elemento do DOM;
- Os dados da instância Vue podem ser mostrados usando uma sintaxe de chaves duplas. Ex: {{ title }};
- Vue é reativo.
O que aprendemos
1º DESAFIO
- Renomear a propriedade meme do objeto data para title, e alterar seu valor para : "Meme Generator".
2. Ciclo de Vida da Instância Vue
Nesse tópico, vamos entender como que funciona o ciclo de vida da instância Vue.
Objetivo
Vamos adicionar o valor do título da página (Meme Generator), somente após a instância for criada.
Ciclo de Vida da Instância
- Cada instância Vue passa por uma série de etapas em usa inicialização - (configurar a observação de dados, compilar o template, montar a instância no DOM, atualizar o DOM quando os dados forem alterados).
- Ao longo do caminho, ocorre a invocação de alguns gatilhos de ciclo de vida, oferecendo a oportunidade de executar lógicas personalizadas em etapas específicas.
beforeCreate() {},
created() {},
beforeMount() {},
mounted() {},
beforeUpdate() {},
updated() {},
beforeDestroy() {},
destroyed() {},
Gatilhos do ciclo de vida da instância
Ciclo de Vida da Instância
data: {
title: 'Meme Generator',
},
created() {
console.log('created');
},
Por exemplo, o gatilho created pode ser utilizado para executar código logo após a instância ser criada:
Diagrama do Ciclo de Vida
2. Ciclo de vida da instância Vue
- A instância Vue, possui gatilhos que permite adicionar códigos específicos durante a criação de sua instância.
O que aprendemos
2º DESAFIO
- Na propriedade data, atribuir o valor de title para ' '.
- Adicionar o valor de title (Meme Generator), no gatilho created da instância.
data: {
title: '',
},
created() {
// setar o title;
},
3. Dados computados
Nesse tópico vamos aprender sobre dados computados, que são propriedades da instância do Vue que calculam valores.
Objetivo
Vamos formatar nosso título de Meme Generator para Meme-Generator, salvando esse valor em um dado computado.
Problema
Queremos formatar nosso título, porém adicionar qualquer lógica mais complexa, pode fazer com que nosso HTML fique com uma manutenção mais complicada. Por exemplo:
<div id="app">
<h1>{{ title.replace(' ', '-') }}</h1>
</div>
Solução
Desde que dados computados calculam um valor no lugar de armazenar um valor, vamos adicionar a opção para dados computados em nossa instância:
Quando o newTitle é chamado, ele faz o replace da string retornando o novo valor. Se o title for atualizado, o dado computado vai atualizar, caso contrário seu valor vai ficar salvo em cache.
data: {...},
computed: {
newTitle() {
return this.title.replace(' ', '-');
},
},
Resultado
<div id="app">
<h1>{{ newTitle }}</h1>
</div>
Outros exemplos
computed: {
fullName() {
return this.firstName + ' ' + this.lastName;
},
showUrl() {
return `${this.url}/${this.id}`;
}
}
3. Dados Computados
- Dados computados calculam valores;
- Dados computados são cacheados, o seu valor só é atualizado quando uma das dependências é atualizada.
( O que aprendemos)
3º DESAFIO
- Remover o dado computado chamado newTitle.
- Criar um novo dado computado, chamado titleFormatted que retorne o título em letras maiúsculas.
4. Renderização condicional
Nesse tópico, vamos explorar maneiras de renderizar condicionalmente algum elemento.
Objetivo
Vamos adicionar uma condição que vai definir se vamos ou não mostrar o título de nossa aplicação.
Problema
- Frequentemente em uma página web, nós queremos que um elemento apareça na página dependendo de alguma condição específica.
Solução - (V-if)
- A solução do Vue é muito simples, nós podemos usar a diretiva v-if / v-else que determina qual elemento ele vai renderizar.
<h1 v-if="showTitle">
{{ titleFormatted }}
</h1>
data: {
showTitle: true
}
Alternando o valor de showTitle para false
data: {
showTitle: false
}
V-if / V-else
<div v-if="emptyTable()">
Nenhum resultado encontrado!
</div>
<div v-else>
<table></table>
</div>
V-if / V-else-if / V-else
<div v-if="isProfessor()">
<h1>Professor</h1>
</h1>
<div v-else-if="isVeterano()">
<p>Veterano</p>
</div>
<div v-else>
<p>Calouro</p>
</div>
V-show
- Se nosso aplicativo tem um elemento que frequentamente é mostrado ou não, é melhor utilizar a diretiva v-show.
- Na diretiva v-show o elemento sempre vai estar disponível no DOM, o que vai alterar é apenas sua visibilidade, sendo a propriedade (display: none;).
- Esse método é mais performático do que inserir ou remover um elemento do DOM várias e várias vezes com o v-if / v-else.
<div v-show="isLoading">
<loader />
</div>
4. Renderização condicional
- Diretivas do Vue para condicionalmente renderizar elementos (v-if / v-else-if / v-else / v-show);
- O elemento só é exibido se a condição dentro da diretiva for verdadeiro;
- Você pode invocar métodos que contém expressões dentro das condições dessa diretiva;
- V-show apenas muda a visibilidade do elemento, ele não insere ou remove um elemento do DOM.
( O que aprendemos)
4º DESAFIO
- Adicionar uma propriedade chamada 'description' no objeto data, com a descrição do app.
- Adicionar a tag <p> abaixo do <h1> mostrando a descrição do app.
- Adicionar uma propriedade chamada showDescription, que vai ter um valor booleano (true/false).
- Adicionar uma diretiva condicional do Vue, que se encaixa nessa situação para mostrar ou não, a descrição do app.
5. Interligações de atributos
Objetivo
Vamos conectar o link de uma imagem
com o elemento <img> em seu atributo src, para mostrar alguma imagem de um meme específico.
Nesse tópico, vamos explorar maneiras de conectar dados aos atributos de elementos HTML.
Encontrar uma imagem - (meme)
Código inicial
index.html
Nós queremos que os dados da imagem, sejam dinamicamente conectados.
Dado do caminho da imagem.
main.js
<div id="app">
<h1 v-if="showTitle">
{{ titleFormatted }}
</h1>
<img src="">
</div>
const app = new Vue({
el: '#app',
data: {
title: '',
image: {
path: './assets/images/dog-meme.png'
},
}
})
Problema
- Nós queremos que a imagem apareça na página, porém de forma dinâmica.
- Dessa maneira, queremos ser capazes de atualizar o source da imagem pelo nosso objeto data e a imagem ser atualizada automaticamente na nossa página.
- Como nosso atributo src da tag <img> é o que encontra o caminho da imagem, nós precisamos que o nosso dado seja interligado com esse atributo src.
Solução
Para víncular o valor do src da imagem no nosso objeto data com nossa tag img, nós vamos usar a diretiva v-bind do Vue.
v-bind
O que vai ser avaliado como:
<img :src="image.path">
<img src="./assets/images/dog-meme.png">
Termo importante: Data Binding
- Quando falamos de Data Binding no Vue, nós queremos dizer que os lugares do HTML que estão ligados e mostrando dados no Vue, estão diretamente conectados com os dados do Vue.
Data Binding
<img :src="image.path">
data: {
image: {
path: './assets/images/dog-meme.png'
},
}
index.html
main.js
Resultado
Alterando a imagem
Se o path da imagem for alterado o src vai atualizar, e a nova imagem vai aparecer.
Isso acontece devido ao src da imagem, estar vinculado com nosso objeto data. (Data Binding)
image: {
path: 'https://imgflip.com/s/meme/Scared-Cat.jpg'
}
Outros tipos de v-bind
<a :href="link">Link</a>
<div :class="divClass">Div</div>
<span :title="tooltip">Span</span>
<button :disabled="isDisabled">Button</button>
5. Interligações de atributos
- Dados podem ser vinculados a elementos HTML;
- Sintaxe para o bind é v-bind ou sua abreviação ':' ;
- O nome do atributo vem depois do : especifica o atributo em que estamos realizando o bind;
- Dentro das aspas dos atributos, está o dado em que estamos referenciando.
v-bind
:
O que aprendemos
:
5º DESAFIO
- Adicione um item chamado title dentro do objeto image.
- Realize o v-bind com o atributo title da tag img adicionando o título do meme.
6. Interligações em formulários
Nesse tópico, vamos aprender como realizar interligações em formulários.
Objetivo
Vamos adicionar um input que será utilizado para escrever sobre a imagem e realizar essa conexão com o que foi digitado.
#main-content {
word-wrap: break-word;
}
#main-image {
width: 100%;
height: auto;
max-height: 800px;
}
.text {
color: #fff;
font-size: 4.5vw;
line-height: 3.8vw;
padding: 15px;
position: absolute;
text-transform: uppercase;
text-shadow: 3px 3px 3px #000;
}
Código inicial - Criar o CSS
assets/css/style.css
Código inicial
Incluir meta tags e bootstrap 4
<head>
<!-- Meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap 4 CSS -->
<link rel="stylesheet" href="https://bootswatch.com/4/lux/bootstrap.min.css">
<!-- Style -->
<link rel="stylesheet" href="./assets/css/style.css">
<!-- Vue.js -->
<script src="https://unpkg.com/vue"></script>
<title>Meme Generator</title>
</head>
Bootstrap 4 - Theme Lux
Customizar layout e adicionar input
<body>
<div id="app" class="row m-0 py-2 text-center">
<div id="main-content" class="col-md-6 d-block mx-auto position relative">
<img id="main-image" :src="image.path" :title="image.title">
</div>
<div class="col-md-6">
<h1 v-if="showTitle" class="mt-2">
{{ titleFormatted }}
</h1>
<div class="form-group">
<input type="text" placeholder="Top text" class="form-control">
</div>
</div>
</div>
<script src="./assets/js/main.js"></script>
</body>
Layout
Texto do input
<p class="fixed-top text">Top text</p>
<img id="main-image" :src="image.path" :title="image.title">
Problema
Como fazer a conexão entre o que digitamos no input, e o texto acima da imagem?
Solução
Precisamos fazer uma interligação entre o input e o elemento <p> acima da nossa imagem usando a diretiva v-model do Vue.
Diretiva V-model
- Você pode usar a diretiva v-model para criar interligações de mão dupla (two-way data binding) entre os dados e elementos como input, textarea e select de formulários.
Alterar a view atualiza o model
Alterar o model atualiza a view
Two-Way Data Binding
Diretiva V-model
data: {
text: {
top: '',
}
},
main.js
<div class="form-group">
<input
type="text"
placeholder="Top text"
class="form-control"
v-model="text.top"
>
</div>
<p class="fixed-top text">
{{ text.top }}
</p>
index.html
index.html
Resultado
Alterar a fonte
- Adicionar uma fonte diferente para o texto do meme - Google Fonts.
- Adicionar a fonte no arquivo style.css, dentro da classe .text (especificar o font-family)
Alterar a fonte - Passion One
<link href="https://fonts.googleapis.com/css?family=Passion+One&display=swap" rel="stylesheet">
index.html
.text {
...,
font-family: 'Passion One';
...
}
style.css
Resultado
6. Interligações em formulários
- A diretiva v-model permite utilizar interligações de mão dupla (two-way data binding).
( O que aprendemos)
6º DESAFIO
- Adicionar um input do tipo texto, abaixo do top input text com o placeholder = Bottom text.
- Adicionar uma propriedade chamada bottom, dentro do objeto text.
- Adicionar uma tag <p> abaixo da imagem com a classe "fixed-bottom text".
- Realizar o two-way data binding (v-model) entre o input e essa tag <p>;
6º DESAFIO
7. Manipulação de eventos
Nesse tópico, vamos aprender como ouvir eventos do DOM para que possamos invocar métodos.
Objetivo
Vamos adicionar um botão chamado reset que quando for clicado, vai limpar o texto dos inputs.
Problema
Nós precisamos de um botão reset para ouvir eventos de click, para então acionar um método que vai limpar o formulário.
Solução
Vamos adicionar o botão com a diretiva v-on do Vue que permite ouvir eventos do DOM, e invocar um método nosso que vai limpar o formulário.
Adicionar o botão
Vamos adicionar o botão abaixo dos inputs
Nós estamos usando a diretiva v-on abreviada = @ para ouvir o evento de click e acionar o método resetInputs()
v-on
@
<button
class="btn btn-outline-primary"
@click="resetInputs()"
>
Reset
</button>
Outros tipos de eventos
// elemento recebeu o foco
@focus="method"
// elemento perdeu o foco
@blur="method"
// botão de submit pressionado
@submit="method"
// qualquer tecla foi pressionada
@keydown="method"
// a tecla foi solta
@keyup="method"
Propriedade methods
A instância Vue tem uma propriedade opcional para seus métodos. Então nós vamos adicionar o método resetInputs que realiza a ação de limpar o formulário
methods: {
resetInputs() {
this.text.top = '';
this.text.bottom = '';
},
},
ES6 - Sintaxe
No lugar de escrever o método como
nós podemos escrever usando a abreviação do ES6 sendo:
São duas maneiras equivalentes de escrever uma função.
resetInputs() {}
resetInputs: function() {}
Resultado
7. Manipulação de eventos
( O que aprendemos)
- A diretiva v-on é usada para permitir que os elementos ouçam os eventos do DOM;
- A abreviação da diretiva v-on é @;
- Você pode especificar o tipo de evento que quer ouvir (click, mouseover, qualquer outro evento do DOM) para invocar seus métodos.
8. Renderização de listas
Nesse tópico, vamos aprender como mostrar listas em nossas páginas usando o Vue.
Objetivo
Mostar uma lista com as cores disponíveis para o texto.
Código inicial
data: {
colors: ['black', 'red', 'white'],
},
main.js
Problema
- Nós precisamos de uma maneira de mostrar as cores para que o usuário possa selecionar, qual que ele deseja ser a cor do texto.
- Como nós podemos iterar o array de cores e mostrar na nossa página?
colors: ['black', 'red', 'white']
main.js
Solução (V-for)
index.html
<div class="form-group">
<label>TEXT COLOR</label>
<span v-for="color in colors">
<span class="ml-2">
{{ color }}
</span>
</span>
</div>
- Outra diretiva do Vue chamada v-for que permite iterar um array para então podermos renderizar os dados dele.
- Vamos adicionar o código abaixo dos inputs.
- Agora temos o nome das cores sendo mostradas, mas como isso está funcionando?
<div v-for="(item, index) in array">
<p>{{ item + '-' + index }}</p>
</div>
data: {
array: ['Fist', 'Second', 'Third']
}
html
js
Diretiva v-for (arrays)
<h1>Students</h1>
<p v-for="student in students">
{{ student.name }}
</p>
data: {
students: [
{ id: 1, name: 'Renan' },
{ id: 2, name: 'Pedro' },
]
}
Diretiva v-for (array de objetos)
js
html
Diretiva v-for (array de objetos)
- Nota que é recomendado usar um atributo key quando for utilizar o v-for, para que o Vue possa manter a identidade de cada item.
:key
<h1>Students</h1>
<p
v-for="student in students"
:key="student.id"
>
{{ student.name }}
</p>
html
Adicionar o atributo :key
<div class="form-group">
<label>TEXT COLOR</label>
<span
v-for="(color, index) in colors"
:key="index"
>
<span class="ml-2">
{{ color }}
</span>
</span>
</div>
index.html
8. Renderização de listas
- A diretiva v-for permite iterar um array para mostrar os dados;
- Nós usamos um apelido para o elemento do array que está sendo iterado, e também especificamos o nome do array em que estamos iterando. Ex: v-for="item in items";
- Nós podemos percorrer um array de objetos e usar a notação de ponto, para acessar os valores dos objetos;
- Quando é usado o v-for é recomendado atribuir uma chave unica a cada elemento em seu atributo :key.
( O que aprendemos)
9. Interligações de classe e estilo
Nesse tópico, vamos aprender como estilizar dinamicamente nosso HTML, realizando a interligações com o atributo style dos elementos e também sua classe.
Objetivo
Adicionar o background do span com a devida cor do array.
Sintaxe de Objeto
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
Você pode usar camelCase ou kebab-case para o nome da propriedade CSS.
A sintaxe Array para v-bind:style permite que você aplique múltiplos objetos de estilo para o mesmo elemento:
<div :style="[baseStyles, overridingStyles]"></div>
Sintaxe de Array
Interligação de estilo
Sintaxe de Objeto
<div :class="{ active: isActive }"></div>
Podemos passar um objeto para o v-bind:class para alternar classes dinamicamente:
data: {
isActive: true
}
<div class="active"></div>
Que vai renderizar no HTML:
Interligação de Classe
Interligação de Classe
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
Que renderizará:
<div class="active text-danger"></div>
Também é possível utilizar uma expressão ternária
<div :class="[isActive ? activeClass : '']"></div>
<div :class="[activeClass, errorClass]"></div>
Sintaxe de Array
Problema
- Nós precisamos de alguma maneira mostrar o background da cor de acordo com o nome da mesma.
- Vamos usar a interligação de estilo inline para dinamicamente setar o background de nosso span, baseado no nosso array de cores.
Solução
:style="{ color: 'red' }"
Solução
Vamos passar a cor para a propriedade do css color.
<div class="form-group">
<label>TEXT COLOR</label>
<span
v-for="(color, index) in colors"
:key="index"
>
<span
id="span-color"
:style="{ background: color }"
>
</span>
</span>
</div>
index.html
#span-color {
border: 1px solid #000;
border-radius: 50%;
cursor: pointer;
display: inline-block;
width: 16px;
height: 16px;
margin-left: 3px;
}
style.css
Resultado
9. Interligações de classe e estilo
- Os elementos HTML podem ser interligados com sua classe ou com seu atributo style de forma dinâmica;
- Nós podemos usar expressões dentro da interligação de classes para avaliar se devemos mostrar uma classe.
( O que aprendemos)
7º DESAFIO
- Adicionar uma propriedade color no objeto text com o valor: 'white';
- Adicionar uma propriedade computada chamada textColor, com o corpo do método:
- Realizar uma interligação de estilo, com as tags <p> e o dado computado textColor = <p :style="textColor"
- Adicionar um método chamado updateTextColor(color), que quando o <span id="span-color"> for clicado, enviar para esse método a cor, e atualizar a cor do texto: this.text.color = color;
return { color: this.text.color };
<p :style="textColor">
this.text.color = color;
7º DESAFIO
10. Componentes
-
Nesse tópico, vamos aprender sobre os componentes.
-
Componentes são blocos reusáveis de código que possuem estrutura e funcionalidade.
Objetivo
-
Vamos criar o componente meme-generator, para refatorar nosso código.
Vue CLI
- Vue CLI é uma ferramenta para criar rapidamente aplicações Vue.js;
- Possui um conjunto de configurações de build prontas para um processo de trabalho de front-end moderno;
- Leva apenas alguns minutos para estar pronto e executando com hot-reload, lint ao salvar e empacotamente pronto para distribuição em produção.
Vue CLI - Instalação
npm install -g @vue/cli
# OR
yarn global add @vue/cli
Requisito - Node.js
Vue CLI exige Node.js na versão 8.9 ou acima (recomendado 8.11.0 +). Você pode gerenciar múltiplas versões do Node na mesma máquina usando o nvm ou nvm-windows.
Yarn - instalação ubuntu, instalação windows
Para instalar o Vue-CLI
Checar sua versão
vue --version
Vue create project
Vue CLI
? Please pick a preset: (User arrow keys)
> default (babel, eslint)
Manually select features
> vue create meme-generator
Vue create project
yarn serve
localhost:8080
Estrutura inicial
Problema
- Em uma aplicação Vue, nós não queremos que todos nossos dados, métodos, dados computados, entre outros na raiz da instância Vue.
- Inclusive, nós queremos deixar nosso código modular e mais fácil de trabalhar.
Estrutura
de um
Single File
Component
<template>
<div>
<!-- html -->
</div>
</template>
<script>
export default {
name: 'ComponentName',
data() {
return {
// data
};
},
methods: {
// methods
},
...
};
</script>
<style>
/* css */
</style>
html
js
css
Single File Component
<template>
<p>{{ hello }}</p>
</template>
<script>
export default {
name: 'HelloWorld',
data() {
return {
hello: 'Hello World!'
}
}
}
</script>
<style scoped>
p {
color: blue;
}
</style>
hello-world.vue
<div id="app">
<hello-world />
</div>
index.html
Solução
Vamos criar um componente chamado, meme-generator.vue dentro da pasta components
- kebab-case.vue
- CamelCase.vue
Nomenclatura de componentes
<template>
<div class="row m-0 py-2 text-center">
<!-- html content -->
</div>
</template>
<script>
export default {
name: 'MemeGenerator',
data() {
return {
title: '',
// data content
};
},
computed: {},
created() {},
methods: {},
};
</script>
<style scoped>
/* style.css */
</style>
meme-generator/src/components/meme-generator.vue
meme-generator.vue
<template>
<div id="app">
<meme-generator />
</div>
</template>
<script>
import MemeGenerator from './components/meme-generator';
export default {
name: 'app',
components: {
MemeGenerator
}
}
</script>
meme-generator/src/App.vue
Importar o componente
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<!-- Bootstrap 4 CSS -->
<link rel="stylesheet" href="https://bootswatch.com/4/lux/bootstrap.min.css">
<!-- Font -->
<link href="https://fonts.googleapis.com/css?family=Passion+One&display=swap" rel="stylesheet">
<title>Meme Generator</title>
</head>
<body>
<noscript>
<strong>
We're sorry but meme-generator doesn't work properly without JavaScript enabled.
Please enable it to continue.
</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
meme-generator/public/index.html
Incluir meta tags, bootstrap e fonte
It workss!!
10. Componentes
- Componentes são blocos de código reusáveis;
- Componentes facilitam a manutenção da aplicação.
( O que aprendemos)
11. Eventos customizados
Nesse tópico, vamos aprender a criar nossos eventos customizados.
Objetivo
Criar um componente chamado text-color.vue, e emitir um evento customizado para o componente pai (meme-generator) alterar a cor do texto.
Criar componente - text-color.vue
<template>
<div class="form-group">
<label>TEXT COLOR</label>
<span
v-for="(color, index) in colors"
:key="index"
>
<span
id="span-color"
:style="{ background: color }"
>
</span>
</span>
</div>
</template>
<script>
export default {
name: 'TextColor',
};
</script>
<style scoped>
#span-color {
border: 1px solid #000;
border-radius: 50%;
cursor: pointer;
display: inline-block;
width: 16px;
height: 16px;
margin-left: 3px;
}
</style>
Importar o componente
<text-color />
meme-generator.vue
<script>
import TextColor from './text-color.vue';
export default {
name: 'MemeGenerator',
components: {
TextColor
},
}
</script>
Property colors ir not defined
Componente (Props)
Propriedades são atributos customizados que você pode registrar em um componente
<script>
export default {
name: 'TextColor',
props: {
colors: {
type: Array,
required: true
},
}
};
</script>
text-color.vue
<text-color :colors="colors" />
meme-generator.vue
Propriedades do componente
- Propriedades podem ter tipos, ser obrigatórias, e ter valores default.
props: {
name: {
type: String,
required: true
},
age: {
type: Number,
required: true
},
}
props: {
url: {
type: String,
required: false,
default() {
return '/url';
}
},
canEdit: {
type: Boolean,
required: false,
default() {
return false;
}
},
}
Problema
- Como vou comunicar o componente pai, que preciso atualizar a cor do texto?
Solução
- Criar um evento customizado, para enviar a cor do texto que o usuário clicou para o componente pai atualizar a cor do texto.
Eventos customizados
this.$root.$emit('event-name');
Emitir um evento
Ouvir um evento
this.$root.$on('event-name', (data) => {
// do something;
// this.method();
});
source
source
Componente TextColor
<template>
<div class="form-group">
<label>TEXT COLOR</label>
<span
v-for="(color, index) in colors"
:key="index"
>
<span
id="span-color"
:style="{ background: color }"
@click="emitUpdateTextColor(color)"
>
</span>
</span>
</div>
</template>
<script>
export default {
name: 'TextColor',
props: {
colors: {
type: Array,
required: true
},
},
methods: {
emitUpdateTextColor(color) {
this.$root.$emit('update-text-color', color);
},
},
};
</script>
@click
method
Evento disparado
Componente Meme Generator
export default {
...,
created() {
this.setTitle();
this.onUpdateTextColor();
},
methods: {
onUpdateTextColor() {
this.$root.$on('update-text-color', (color) => {
this.updateTextColor(color);
})
},
updateTextColor(color) {
this.text.color = color;
}
}
}
11. Eventos customizados
- Um componente pode emitir eventos com o $emit;
- Um componente pode ouvir eventos com o $on;
- Um componente pode emitir dados em conjunto com o evento $emit.
( O que aprendemos)
12. Desafios
- Criar memes com o gerador de memes, e postar nos comentários abaixo!
- Salvar imagem com print (linux: Fn + Shift + Prt Sc)
Desafio - nível VERY EASY
Desafio - nível VERY EASY
- Adicionar um input que recebe a url da imagem, e atualiza a imagem na hora;
Desafio - nível EASY
- Adicionar um input para alterar o tamanho da fonte dos textos, que recebe o valor da fonte. Ex: 30px, 50px, etc.
Desafio - nível EASY
- Criar uma opção parecida com a TEXT COLOR para alterar a sombra da descrição do texto do meme, chamado TEXT SHADOW COLOR.
Desafio - nível EASY
- Criar um checkbox com o texto UPPERCASE que quando for marcado alterar o :style do texto para letras maiúsculas e quando desmarcado alterar para letras minúsculas;
Desafio - nível MEDIUM
- Criar um select para alterar o tipo de fonte utilizada no gerador de meme.
Desafio - nível MEDIUM
- Criar um componente chamado MEME GALLERY, que contém uma galeria de memes, que quando clicado na imagem atualiza o meme atual.
Desafio - nível HARD
- Adicionar um botão de DOWNLOAD que realiza o download da imagem do MEME.
Desafio - nível HARD
Referências
Cursos - Vue Mastery
Cursos - Vue School
Links úteis
- Awesome Vue - (Lista de items relacionados ao Vue.js)
- Made with Vue.js - (Lista de apps feitos em Vue.js)
Obrigado!
Introdução ao Vue.js
By Renan Gabriel
Introdução ao Vue.js
- 763