|
|
|
|
|
|
|
![VueJS](http://us.vuejs.org/_nuxt/img/vuesplash.3e416f3.png)
|
|
|
|
# VueJS
|
|
|
|
> Tutorial passo a passo de como trabalhar com Vue, criar rotas, componentes e páginas.
|
|
|
|
|
|
|
|
|
|
|
|
## Inicio
|
|
|
|
Esta página contém um rápido tutorial que poderá servir de apoio para o desenvolvimento de qualquer aplicação front-end com VueJS.
|
|
|
|
O principal objetivo desse guia é explicar como funciona o fluxo em uma aplicação com o framework da forma mais prática possível. Portanto, não é seguido o [guia de melhores práticas](https://br.vuejs.org/v2/style-guide/index.html).
|
|
|
|
|
|
|
|
Como base, será utilizado uma simples aplicação de autenticação com cadastro e login.
|
|
|
|
O código completo pode ser encontrado no seguinte repositório:
|
|
|
|
- Aplicação: https://marlonfurtado.github.io/vuejs-auth/
|
|
|
|
- Repositório: https://github.com/marlonfurtado/vuejs-auth
|
|
|
|
|
|
|
|
_______________________________________
|
|
|
|
|
|
|
|
|
|
|
|
## Pré-Requisitos
|
|
|
|
- NodeJs e NPM (obrigatório)
|
|
|
|
- Editor *Visual Studio Code* (recomendável)
|
|
|
|
- Extensão para o VS Code: **Vetur** (recomendável)
|
|
|
|
1. Abra o editor
|
|
|
|
2. `Ctrl + Shift + X`, para abrir as extensões
|
|
|
|
3. Procure por `Vetur`
|
|
|
|
4. Clique em `install`, e depois `reload`.
|
|
|
|
|
|
|
|
_______________________________________
|
|
|
|
|
|
|
|
|
|
|
|
## 1. Estrutura do projeto
|
|
|
|
Em uma estrura com **vue-loader** e **webpack**, como a que estamos usando no projeto [Arbitrium](), a criação de páginas, componentes e o desenvolvimento da aplicação se resumem em basicamente três pastas (não serão as únicas, mas as principais no processo de desenvolvimento). São elas:
|
|
|
|
|
|
|
|
- */src/components/*
|
|
|
|
- */src/pages/*
|
|
|
|
- */src/router/*
|
|
|
|
|
|
|
|
|
|
|
|
### 1.1. Components
|
|
|
|
> /src/components/
|
|
|
|
|
|
|
|
*// TODO*
|
|
|
|
|
|
|
|
### 1.2. Pages
|
|
|
|
> /src/pages/
|
|
|
|
|
|
|
|
*// TODO*
|
|
|
|
|
|
|
|
### 1.3. Router
|
|
|
|
> /src/router/
|
|
|
|
|
|
|
|
*// TODO*
|
|
|
|
|
|
|
|
|
|
|
|
_______________________________________
|
|
|
|
|
|
|
|
|
|
|
|
## 2. Passo a Passo
|
|
|
|
O componente usado como exemplo é o de uma notificação de erro, caso o usuário digite seus dados errados ou aconteça algum erro com o banco de dados.
|
|
|
|
|
|
|
|
![notification](/uploads/aabc2bf90b2d9a3f25f544a767e1d329/notification.png)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 2.1 Criando uma página
|
|
|
|
Para criar uma página é simples.
|
|
|
|
- Na pasta `src/pages/` crie um arquivo com a extensão `.vue`. O nome do arquivo, preferencialmente, deve ser o mesmo do nome da rota que será acessado na URL. Aqui criaremos o uma página `Test.vue`.
|
|
|
|
|
|
|
|
- Dentro do arquivo, crie o template inicial:
|
|
|
|
|
|
|
|
```
|
|
|
|
<template>
|
|
|
|
<!-- HTML -->
|
|
|
|
</template>
|
|
|
|
<script>
|
|
|
|
// JS
|
|
|
|
</script>
|
|
|
|
<style>
|
|
|
|
/* CSS */
|
|
|
|
</style>
|
|
|
|
```
|
|
|
|
|
|
|
|
- A página terá apenas um *input* de senha e um botão.
|
|
|
|
|
|
|
|
```
|
|
|
|
<template>
|
|
|
|
<div class="row mt-4">
|
|
|
|
<div class="col-md-5"></div>
|
|
|
|
<div class="form-inline">
|
|
|
|
<div class="form-group mx-sm-3 mb-2">
|
|
|
|
<label for="password" class="sr-only">Password</label>
|
|
|
|
<input type="password" class="form-control" id="input-password" placeholder="Password">
|
|
|
|
</div>
|
|
|
|
<div class="col-md-7 ml-1 mt-1">
|
|
|
|
<button class="btn btn-primary mb-2">Confirm identity</button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
```
|
|
|
|
|
|
|
|
- Agora é preciso iniciar a instância Vue dentro do `<script>`. Ainda sem muita lógica.
|
|
|
|
|
|
|
|
```
|
|
|
|
export default {
|
|
|
|
name: "Test",
|
|
|
|
data: () => {
|
|
|
|
return {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
- Como estamos usando Bootstrap para essa página, então não foi preciso mexer na tag `<style>`.
|
|
|
|
|
|
|
|
__________________________
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### 2.2 Criando uma rota
|
|
|
|
Com a página criada é preciso criar uma rota para poder acessá-la.
|
|
|
|
- Em `src/router/index.js` é onde fica o arquivo que gerencia as rotas e cada página da aplicação.
|
|
|
|
- Se a aplicação foi criada com o `vue-cli` (caso do Arbitrium), então já deve ter uma estrutura criada com uma instância de `Route`. Algo como: `let router = new Router({ router: [] })`, onde o argumento passado dentro de `Router` é um array com o caminho de todas as rotas do projeto. Como no exemplo abaixo.
|
|
|
|
|
|
|
|
```
|
|
|
|
import Home from '@/components/Home'
|
|
|
|
import Login from '@/components/Login'
|
|
|
|
let router = new Router({
|
|
|
|
routes: [
|
|
|
|
{
|
|
|
|
path: '/home',
|
|
|
|
name: 'Home',
|
|
|
|
component: Home,
|
|
|
|
meta: {
|
|
|
|
requireAuth: true
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
path: '/login',
|
|
|
|
name: 'Login',
|
|
|
|
component: Login
|
|
|
|
},
|
|
|
|
]
|
|
|
|
})
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- Nesse arquivo é necessário apenas importar a nova página (ou componente) e criar um novo objeto dentro do array com as informações do novo caminho.
|
|
|
|
|
|
|
|
```
|
|
|
|
import Test from '@/pages/Test'
|
|
|
|
routes: [
|
|
|
|
{
|
|
|
|
path: '/test',
|
|
|
|
name: 'Test',
|
|
|
|
component: Test
|
|
|
|
}
|
|
|
|
]
|
|
|
|
```
|
|
|
|
|
|
|
|
- Para testar a nova rota é só acessá-la no seu navegador *(provavelmente em http://localhost:8080/test)*
|
|
|
|
|
|
|
|
___________________________________
|
|
|
|
|
|
|
|
|
|
|
|
#### 2.3 Criando um componente
|
|
|
|
- Dentro da pasta `/src/components/` crie um arquivo com a extensão `.vue`. O nome do arquivo deve ser o nome do componente de forma que facilite sua identificação. Por exemplo, um componente que retorna um erro, pode ser chamado de `ErrorNotification.vue`
|
|
|
|
|
|
|
|
- Dentro do arquivo, crie o template inicial do componente (o mesmo que foi visto para criar uma página). Esse é o template padrão que usaremos para todos arquivos com a extensão `.vue`.
|
|
|
|
|
|
|
|
- Começando pelo HTML. Como o componente é simples, uma `<div>` com as mensagens de erro dentro, e um `<button>` para fechar a notificação são o suficiente.
|
|
|
|
|
|
|
|
```
|
|
|
|
1. <template>
|
|
|
|
2. <div id="notification" class="alert alert-danger">
|
|
|
|
3. <button @click="close()" class="close"><span aria-hidden="true">×</span></button>
|
|
|
|
4. <p>Code: {{code || '0'}}</p>
|
|
|
|
5. <p>{{message || 'Sorry, an error occurred.'}}</p>
|
|
|
|
6. <p>Try again, or <router-link to="/signup">create account.</router-link></p>
|
|
|
|
7. </div>
|
|
|
|
</template>
|
|
|
|
```
|
|
|
|
|
|
|
|
- A tag `<script>` é onde está todo o comportamento do componente. E o modelo padrão é sempre algo como:
|
|
|
|
|
|
|
|
```
|
|
|
|
<script>
|
|
|
|
1. export default {
|
|
|
|
2. name: 'ErrorNotification',
|
|
|
|
3. props: ['code', 'message'],
|
|
|
|
4. data: () => {
|
|
|
|
5. return {}
|
|
|
|
6. },
|
|
|
|
7. methods: {
|
|
|
|
8. close: function() {
|
|
|
|
9. document.querySelector('#notification').classList.add('d-none')
|
|
|
|
10. }
|
|
|
|
11. }
|
|
|
|
12. }
|
|
|
|
</script>
|
|
|
|
```
|
|
|
|
|
|
|
|
- O `export default { ... }` *(linha 1)* é como se fizesse um `export new Vue({})`. Ou seja, o que está dentro de `{ ... }` são os objetos ou métodos de uma **instância** de Vue.js
|
|
|
|
- O `data` *(linha 4)* são os dados que circulam no componente. Esse é um dos pontos principais da *reatividade* de Vue. Deve ser sempre uma **função** que retorna um **objeto**. Por exemplo, como teste, você pode criar uma variável dentro de `data` e mostrar ela na tela.
|
|
|
|
|
|
|
|
```
|
|
|
|
data: () => {
|
|
|
|
return {
|
|
|
|
message: 'Hello World!',
|
|
|
|
}
|
|
|
|
},
|
|
|
|
```
|
|
|
|
|
|
|
|
Com a variável criada, é só colocar ela no HTML com a sintaxe: `{{message}}`. Exatamente como é no Angular.
|
|
|
|
|
|
|
|
- O `props` *(linha 3)* deve ser um array, e assim como no React.js, são os dados que vem do elemento pai e é colocado no componente como se fosse um atributo normal. Será usado mais a frente para pegar o código e a mensagem de erro.
|
|
|
|
|
|
|
|
- O `methods` *(linha 7)* também será bastante usado. Dentro dele vai os métodos que serão usados no componente. Por exemplo, ao clicar no botão de *fechar*, o método `close()` é chamado para fechar a notificação.
|
|
|
|
|
|
|
|
> Veja mais em: https://medium.com/emanuelg-blog/descomplicando-os-single-file-components-do-vue-js-2df16724baab
|
|
|
|
|
|
|
|
__________________________________
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### 2.3 Chamando o componente na página
|
|
|
|
- Com o componente pronto, agora é preciso chamá-lo na nossa página. Para isso, vá no arquivo da pagina de Test, dentro da tag de `<script>`
|
|
|
|
|
|
|
|
- Primeiro é preciso importar o componente:
|
|
|
|
`import ErrorNotification from '../components/ErrorNotification'`
|
|
|
|
|
|
|
|
- E depois declarar o componente no objeto `components`:
|
|
|
|
`components: { ErrorNotification },`
|
|
|
|
|
|
|
|
- Em `data` é onde vai nossas variáveis, por exemplo: *password, ErrorCode e ErrorMessage*
|
|
|
|
|
|
|
|
- E para finalizar o script é preciso criar nosso método de validação que é onde vai estar a lógica para mostrar o componente. Se errar a senha, então as variáveis recebem um valor, e esse valor é passado para o componente mostrar o erro e a mensagem. Por exemplo, a função *validate()* é criada abaixo e depois chamada no HTML. (código completa mais abaixo)
|
|
|
|
|
|
|
|
```
|
|
|
|
methods: {
|
|
|
|
validated: function() {
|
|
|
|
if (this.password !== 'password') {
|
|
|
|
this.errorCode = 666
|
|
|
|
this.errorMessage = "Senha inválida"
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
this.errorCode = null
|
|
|
|
this.errorMessage = null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
- Com todo o script de controle da página pronto, agora é arrumar o HTML. O template final do HTML fica como abaixo:
|
|
|
|
|
|
|
|
```
|
|
|
|
1. <template>
|
|
|
|
2. <div class="row mt-4">
|
|
|
|
3. <div class="col-md-5"></div>
|
|
|
|
4. <div class="form-inline">
|
|
|
|
5. <div class="col-md-7 ml-1 mt-1">
|
|
|
|
6. <div class="form-group mx-sm-3 mb-2">
|
|
|
|
7. <label for="password" class="sr-only">Password</label>
|
|
|
|
8. <input type="password" v-model="password" class="form-control" id="input-password" placeholder="Password">
|
|
|
|
9. </div>
|
|
|
|
10. </div>
|
|
|
|
11. <div class="col-md-5 ml-1 mt-1">
|
|
|
|
12. <button @click="validated()" class="btn btn-primary mb-2">Confirm identity</button>
|
|
|
|
13. </div>
|
|
|
|
14. </div
|
|
|
|
15. <!-- ERROR NOTIFICATION -->
|
|
|
|
16. <ErrorNotification v-show="errorCode" :code="errorCode" :message="errorMessage"></ErrorNotification>
|
|
|
|
17. </div>
|
|
|
|
18. </template>
|
|
|
|
```
|
|
|
|
|
|
|
|
- As classes utilizadas são todas do Bootstrap, e a maioria dessas são para alinhamento, para mais informações pode ser consultado a documentação do Bootstrap.
|
|
|
|
|
|
|
|
- Na **linha 8** é onde está o input de password com a diretiva `v-model`, exatamente como no Angular, essa diretiva é responsável por fazer a conexão *([two-way data biding](https://alligator.io/vuejs/v-model-two-way-binding/))* de um dado no HTML para o tratamento no *script*. No exemplo estamos passando a senha que o usuário digitar para o atributo `password` dentro de **data()** no script.
|
|
|
|
|
|
|
|
- A **linha 12** é um botão com a diretiva `@click` que captura a ação do usuário. Quando clicar no botão a função *validated()* é chamada.
|
|
|
|
|
|
|
|
- Na **linha 16** é onde chamamos o componente de erro que foi criado. O componente funciona como uma tag de HTML normal podendo receber inclusive class ou id. No exemplo, o componente tem uma diretiva `v-show` que é uma condição para ele ser exibido. Se aquela variável for `true`, então o componente é mostrado. A variável `errorCode` tambem está presente na função `data()` no script e é atribuido um valor quando a função `validated()` é chamada.
|
|
|
|
|
|
|
|
- Ainda na **linha 16** tem `:code` e `:message` que funcionam como parâmetros passados para o componente. No exemplo, passamos os atributos de **erro**, que no arquivo de componente `ErrorNotification.vue` eles são tratados no `props: ["code", "message"]`.
|
|
|
|
|
|
|
|
- O resultado final da página ficou como abaixo:
|
|
|
|
|
|
|
|
```
|
|
|
|
<template>
|
|
|
|
<div class="row mt-4">
|
|
|
|
<div class="col-md-5"></div>
|
|
|
|
<div class="form-inline">
|
|
|
|
<div class="col-md-7 ml-1 mt-1">
|
|
|
|
<div class="form-group mx-sm-3 mb-2">
|
|
|
|
<label for="password" class="sr-only">Password</label>
|
|
|
|
<input type="password" v-model="password" class="form-control" id="input-password" placeholder="Password">
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="col-md-5 ml-1 mt-1">
|
|
|
|
<button @click="validated()" class="btn btn-primary mb-2">Confirm identity</button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- ERROR NOTIFICATION -->
|
|
|
|
<ErrorNotification v-show="errorCode" :code="errorCode" :message="errorMessage"></ErrorNotification>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
<!-- SCRIPTS -->
|
|
|
|
<script>
|
|
|
|
import ErrorNotification from '../components/ErrorNotification'
|
|
|
|
export default {
|
|
|
|
name: "Test",
|
|
|
|
components: {
|
|
|
|
ErrorNotification
|
|
|
|
},
|
|
|
|
data: () => {
|
|
|
|
return {
|
|
|
|
password: '',
|
|
|
|
errorCode: null,
|
|
|
|
errorMessage: null
|
|
|
|
}
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
validated: function() {
|
|
|
|
if (this.password !== 'password') {
|
|
|
|
this.errorCode = 666
|
|
|
|
this.errorMessage = "Senha inválida"
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
this.errorCode = null
|
|
|
|
this.errorMessage = null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
```
|
|
|
|
|
|
|
|
|