Primeiras aulas do curso Vue.js parte 2: construindo Single Page Applications

Vue.js parte 2: construindo Single Page Applications

Criando nossa própria diretiva - Atendendo mais um pedido do design

Começando deste ponto? Você pode fazer o DOWNLOAD completo do projeto do capítulo anterior e continuar seus estudos a partir deste capítulo. Será necessário abrir seu terminal, entrar dentro da pasta alurapic e executar o comando npm install para baixar novamente todas as dependências da aplicação.

Até o momento, aprendemos a criar componentes reutilizáveis extremamente úteis. No entanto, o meu designer, que vocês já devem ter percebido que é meu amigo imaginário, me pediu para implementar a seguinte funcionalidade em nossa aplicação.

Toda vez que dermos um duplo clique na imagem do painel ela será rotacionada 90 graus. Mas ele esta na dúvida se gira imagem mesmo ou o próprio painel como um todo. Sendo assim, precisaremos fazer a rotação com os dois componentes e verificar em qual deles o efeito fica mais interessante.

Podemos quebrar a cabeça um pouco e criar métodos ou computed properties em nossos componentes, inclusive trabalhar com eventos para implementar essa solução. Se vamos conseguir não tenho certeza, mas mesmo que consigamos se quisermos usar essa mesma funcionalidade em outros componentes precisaremos repetir seu código o que torna a manutenção da aplicação mais complicada. Par solucionar problemas como esse o Vue possui as diretivas.

Diretivas vs Componentes

Diretivas são blocos de código isolados que operam sobre componentes e que manipulam o DOM apenas, diferente de componentes que são unidades confinadas de código que possuem sua apresentação e lógica. Inclusive, já usamos algumas diretivas do Vue como v-for, v-show entre outras.

Talvez você tenha torcido o nariz quando escutou a frame "manipulação de DOM", pois é exatamente a manipulação de DOM que o Vue tenta evitar com seus mecanismos de data binding. No entanto, esse tipo de manipulação é totalmente permitida dentro das diretivas.

Criando nossa própria diretiva - Criando nossa primeira diretiva

Vamos iniciar os trabalhos criando o arquivo alurapic/src/directives/Transform.js. Veja que o arquivo não é um single file template com a extensão .vue, mas um arquivo .js como outro script qualquer.

// alurapic/src/directives/Transform.js

import Vue from 'vue';

Veja que a primeira instrução da nossa diretiva é a importação do global view object Vue. É através dele que registraremos nossa diretiva para que seja acessível pelas views da nossa aplicação.

O próximo passo é invocar o método Vue.directive que recebe como parâmetro o nome da diretiva e como segundo um objeto JavaScript que conterá as configurações da diretiva:

// alurapic/src/directives/Transform.js

import Vue from 'vue';

Vue.directive('meu-transform', {

  /* ainda sem qualquer configuração */

});

Nossa diretiva ainda não esta completa, mas quando formos utilizá-la em nossos template somos obrigados a utilizar o prefixo v-. Veja que diretivas como v-for e v-show possui o mesmo prefixo. Sendo assim, para utilizarmos nossa diretiva precisaremos fazer v-meu-transform.

A função bind e acesso ao elemento do DOM

Agora que você já entendeu como usaremos a diretiva que estamos criando em nossos templates podemos partir para sua configuração. O objeto passado como segundo parâmetro precisa ter o método bind, um hook chamado toda vez que a diretiva é associada ao elemento do DOM. O método recebe três parâmetros. O nome desses três parâmetros podem ser qualquer um, no entanto vamos utilizar aqueles que deixaram claro o papel de cada um:

// alurapic/src/directives/Transform.js

import Vue from 'vue';

Vue.directive('meu-transform', {

    bind(el, binding, vnode) {

    }

});

Por enquanto, vamos no ater apenas ao primeiro parâmetro da diretiva, que nada mais é do que o elemento do DOM no qual a diretiva esta sendo aplicada. Vamos imprimir no console esse parâmetro:

// alurapic/src/directives/Transform.js

import Vue from 'vue';

Vue.directive('meu-transform', {

    bind(el, binding, vnode) {

        console.log('Diretiva iniciada');
        console.log(el);

    }

});

Por enquanto vamos deixar essa implementação e experimentar utilizá-la em nossa aplicação.

Importando nossa diretiva

Em nenhum momento carregamos o módulo Transform.js. Todo arquivo .js e .vue criados são módulos que precisam ser importados. Faremos isso em nosso arquivo alurapic/src/main.js:

// alurapic/src/main.js

import Vue from 'vue'
import App from './App.vue'
import VueResource from 'vue-resource';
import VueRouter from 'vue-router';

import { routes } from './routes';

// importando o arquivo `Transform.js`.
import './directives/Transform';

Vue.use(VueRouter);

// código posterior omitido

Veja que a cláusula import precisa receber apenas o caminho do arquivo. É desta forma porque o módulo Transform.js não exporta código algum, precisamos apenas carregá-lo para que nossa diretiva seja registrada através do global view object. Excelente! Isso já é suficiente para que nossa diretiva esteja ativa.

Agora, vamos abrir alurapic/src/components/home/Home.vue e adicionar a diretiva no elemento <imagem-responsiva/>:

<!-- alurapic/src/components/home/Home.vue -->

<!-- código anterior omitido -->

<imagem-responsiva :url="foto.url" :titulo="foto.titulo" v-meu-transform/>

<!-- código posterior omitido

Não esqueça que o Vue CLI precisa estar de pé para que possamos visualizar o resultado em nosso navegador. Assim que a página for atualizada, abra o console do navegador e veja o resultado. Veja que para cada componente ele exibirá o elemento do DOM correspondente àquele componente.

Agora que já vimos que nossa diretiva esta atuando para cada componente ImagemResponsiva criado dinamicamente através da diretiva v-for podemos dar início a implementação da lógica de rotação.

Um ponto importante é que cada diretiva é aplicada isoladamente para cada elemento, sendo assim, cada diretiva pode ter suas variáveis de controle específicas para cada elemento. No caso, vamos declarar a variável current que será iniciada assim que nossa diretiva for aplicada no elemento. Ela guardará o eixo atual utilizado para rotacionarmos o elemento. Todos começarão de zero:

// alurapic/src/directives/Transform.js

import Vue from 'vue';

Vue.directive('meu-transform', {

    bind(el, binding, vnode) {
      let current = 0;

    }

});

Implementando nossa lógica

A cada duplo clique que realizamos, vamos incrementar a variável current em 90 graus. Mas como trabalharemos com evento dentro da nossa diretiva? Se fosse no componente, poderíamos usar @dblclick no template, mas veja que aqui não temos template. A boa notícia é o fato de el ser o elemento do DOM no qual a diretiva esta associada e, sendo um elemento do DOM, podemos adicionar evento da maneira tradicional no mundo JavaScript através de addEventListener:

// alurapic/src/directives/Transform.js

import Vue from 'vue';

Vue.directive('meu-transform', {

    bind(el, binding, vnode) {
      let current = 0;
      el.addEventListener('dblclick', function() {
        current+=90;
      });
    }

});

A cada clique o valor de current da imagem que estamos clicando será incrementado. Agora, basta aplicamos uma transformação do tipo rotate do CSS para conseguimos o evento desejado. Via DOM, aplicamos um estilo diretamente no elemento através de elemento.style.nomeDoPropriedade:

// alurapic/src/directives/Transform.js

import Vue from 'vue';

Vue.directive('meu-transform', {

    bind(el, binding, vnode) {
      let current = 0;
      el.addEventListener('dblclick', function() {
        current+=90;
        this.style.transform = `rotate(${current}deg)`;
      });
    }

});

Aqui usamos template string do ES2015 para nos ajudar a construir a string dinamicamente com base no valor atual da variável current. Muito mais interessante do que se tivéssemos feito uma concatenação. Templates strings são criadas usando crase (backstick) e no lugar da concatenação, usamos ${nomeDaVariavel} para interpolar dentro da string valores de variáveis. Se você quer saber mais sobre ES2015 e template strings, sugiro cursar meu curso de JavaScript avançado aqui da Alura.

Vamos testar o resultado? Com a página recarregada, quando clicamos duas vezes nas imagens elas são rotacionadas de 90 em 90 graus. No diretiva é tão genérica que podemos adicioná-la ao título da página, permitindo sua rotação no duplo clique:

<!-- alurapic/src/components/home/Home.vue -->

<template>
    <div>    
        <h1 class="centralizado" v-meu-transform>Alurapic</h1>

<!-- código posterior omitido -->

Faça um teste e veja o resultado!

Excelente. Mas se quisermos incrementar de 50 em 50? Para isso nossa diretiva precisará receber a quantidade em graus do incremento. É isso que veremos no próximo vídeo.

Criando nossa própria diretiva - Passagem de parâmetros

Podemos passar parâmetros para nossa diretiva. No caso, vamos fazer com que a rotação de cada imagem seja feita de 15 em 15 graus:

<!-- alurapic/src/components/home/Home.vue -->

<!-- código anterior omitido -->

<imagem-responsiva :url="foto.url" :titulo="foto.titulo" v-meu-transform="15"/>

<!-- código posterior omitido -->

Veja que atribuímos o valor 15 à nossa diretiva no template de Home.vue. Agora, no código de nossa diretiva, precisamos ter acesso a esse valor. Isso é possível através de binding.value:

// alurapic/src/directives/Transform.js

import Vue from 'vue';

Vue.directive('meu-transform', {

    bind(el, binding, vnode) {
      let current = 0;
      el.addEventListener('dblclick', function() {
        let incremento = binding.value || 90;
        current+=incremento;
        this.style.transform = `rotate(${current}deg)`;
      });
    }

});

Se não for passado parâmetro algum, usaremos 90 por padrão. Caso seja, utilizaremos o valor passado como parâmetro para rotacionar nosso elemento. Faça um teste. Veja que a imagem é incrementa de 15 em 15 graus e nosso título de 90 em 90, porque não passamos nenhum parâmetro.

Para ficar ainda melhor, podemos executar uma transição na rotação:

import Vue from 'vue';

Vue.directive('meu-transform', {

    bind(el, binding, vnode) {
      let current = 0;
      el.addEventListener('dblclick', function() {
        let incremento = binding.value || 90;
        current+=incremento;
        this.style.transition = "transform 0.5s";
        this.style.transform = `rotate(${current}deg)`;
      });
    }

});

Tudo funciona perfeitamente. Mas se quisermos alterar o tempo de transição? Veja que usamos o valor fixo de meio segundo. Nossa diretiva já recebe um parâmetro que é a quantidade de graus que desejamos rotacionar, e agora?

Passando mais de um parâmetro

Podemos passar um objeto JavaScript como parâmetro para a diretiva no qual cada propriedade é um parâmetro da diretiva. Alterando Home.vue:


<!-- alurapic/src/components/home/Home.vue -->

<!-- código anterior omitido -->

<imagem-responsiva :url="foto.url" :titulo="foto.titulo" v-meu-transform="{incremento: 15, animate: true}"/>

<!-- código posterior omitido -->

Agora, alterando a lógica do nosso hook binding:

import Vue from 'vue';

Vue.directive('meu-transform', {

    bind(el, binding, vnode) {

      let current = 0;

      el.addEventListener('dblclick', function() {

        let incremento = 90;
        let animate = false;

        if(binding.value) {
            incremento = binding.value.incremento
            animate = binding.value.animate 

        }

        current+=incremento;
        this.style.transform = `rotate(${current}deg)`;
        if (animate) this.style.transition = "transform 0.5s";

      });
    }

});

Apesar de funcional, podemos fazer um pouquinho diferente. É isso que veremos no próximo vídeo.

Sobre o curso Vue.js parte 2: construindo Single Page Applications

O curso Vue.js parte 2: construindo Single Page Applications possui 185 minutos de vídeos, em um total de 72 atividades. Gostou? Conheça nossos outros cursos de Frameworks MVC em Front-end, ou leia nossos artigos de Front-end.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Frameworks MVC acessando integralmente esse e outros cursos, comece hoje!

  • 1124 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

Premium

  • 1124 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$75
à vista R$900
Matricule-se

Premium Plus

  • 1124 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$100
à vista R$1.200
Matricule-se

Max

  • 1124 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$120
à vista R$1.440
Matricule-se
Procurando planos para empresas?
Acesso por 1 ano
Estude 24h/dia onde e quando quiser
Novos cursos toda semana