vue-js-fundamentos

Vue.js fundamentos básicos

Neste tutorial apresento os fundamentos básicos do Vue.js que consistem no mínimo necessário que um desenvolvedor necessita saber para iniciar seus estudos deste framework.

O texto foi escrito visando auxiliar sobretudo os desenvolvedores Laravel que estão iniciando seus estudos no Vue.js

Conceitos

Em uma tradução livre da documentação do Vue.js temos a seguinte definição:

O Vue (pronunciado |viu|) é um framework progressivo para a construção de interfaces de usuário. Diferente de outros frameworks monolíticos, o Vue foi projetado desde o início para possibilitar que seja adotado de forma incremental. Sua biblioteca central está focada somente na camada view, sendo fácil agregar e integrar a outras bibliotecas e/ou projetos.

Por outro lado, o Vue é perfeitamente capaz de suportar sofisticadas aplicações de página única (SPA) quando usado em conjunto com ferramentas e bibliotecas de suporte modernas.




Abaixo forneço alguns conceitos relacionados ao estudo do Vue.js que são importantes para o entendimento de seu funcionamento.

DOM

Aplicando ao contexto de uma página da web o DOM é uma representação da página que está sendo exibida no browser a qual é representada como um modelo de documento cuja estrutura é uma árvore invertida.

Nesta árvore, conforme ilustração abaixo, seu título será document e sua raiz o elemento html, partindo dele os ramos correspondentes aos elementos head e body. A estrutura prossegue, conforme os elementos que estejam contidos na página em questão.

As folhas representam o conteúdo final exibido entre as tags html e seu valor pode ser recuperado e alterado usando as funções padrão conforme a implementação do modelo DOM.

Na programação da interface com o usuário este modelo é utilizado para a permitir acesso aos atributos e métodos dos elementos da árvore.

Este modelo também comtempla os eventos capturados pela interface de usuário como cliques em botões, passagem do mouse e digitação de texto.

Um conceito mais completo e formal pode ser lido na referência abaixo.

Referência: https://developer.mozilla.org/pt-BR/docs/DOM/Referencia_do_DOM

Reatividade

Este conceito diz respeito ao fato de mudanças nas variáveis serem refletidas de forma automática e imediata nas interfaces que as referenciam. O nome do conceito faz alusão ao fato de que a interface “reage”, ou seja, auto atualiza de forma assíncrona, às mudanças nas propriedades ou variáveis.

Progressividade

Este conceito quando aplicado ao Vue.js significa que ele é um framework de adoção progressiva por dois motivos: primeiro porque, no caso de grandes aplicações, pode ser adotado de forma gradativa em partes da aplicação. Segundo, porque é um framework enxuto, seu núcleo trata apenas da camada view, cujas funcionalidades podem ser ampliadas à medida que for necessário mediante o uso de bibliotecas e outras ferramentas.

Data binding

Qualquer aplicativo que interaja com o usuário exibindo (saídas) e recebendo (entradas) trabalha com o conceito de data binding. Por este conceito existe um modelo de dados (Model) onde, em linhas gerais, as informações são armazenadas. Separada deste modelo existe a interface (View) responsável por exibir aos usuários as informações que estão guardadas nos modelos.

O data binding é a operação de ligar / conectar (bind) dados específicos do modelo aos elementos da interface, de modo a que mudanças nos dados também ocorram nos elementos correspondentes da interface.

Quando é possível apenas que alterações nos dados ocasionem mudanças na interface chamamos de one-way data binding. E no caso de mudanças na interface ocasionarem alterações nos dados e vice-versa recebe a denominação de two-way data binding.

Uma das motivações para a criação do Vue.js e de outros frameworks foi a complexidade de realizar o data binding em aplicativos JavaScript puros. Com este framework, como veremos neste texto, é possível realizar o one-way ou o two-way data binding de forma bastante simplificada.

Diretivas

No contexto do Vue.js são as instruções iniciadas por v- (vê hífen) que comandam o framework para que realize determinadas ações ou tenha certos comportamentos. Além do conjunto de diretivas que fazem parte do núcelo do Vue.js também é possível ao usuário criar suas próprias diretivas personalizadas.




Instalação

Para fazer as primeiras experiências em nosso tutorial de Vue.js basta ter um browser compatível com JavaScript (mais especificamente o ECMAScript 5 ou posterior), o que representa quase a totalidade dos navegadores atuais, não sendo necessário instalar nenhum software adicional.

Conforme você for aprofundando o estudo e aprendendo mais a respeito do framework e, como consequência, trabalhando em projetos maiores, sentirá a necessidade de instalar o Vue.js em seu ambiente de desenvolvimento.

Pois, além do core poderá usar outros softwares de apoio que fazem parte do pacote, como: empacotadores, transpiladores, compiladores e outros; e também a CLI (command line interface) usada, entre outras coisas, para gerar esqueletos de aplicativos Vue.

CDN

Neste texto iremos fazer uso da instalação a partir de uma CDN, que consistirá simplesmente em inserir um link para o Vue.js em uma página HTML. Assim sendo, crie o arquivo vue-iniciante.html e nele digite o seguinte código:

<!DOCTYPE html>
<html lang="pt-br">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <title>Vue Iniciante</title>
</head>
<body>
    <div id="app">
        <h1>{{ header ? header : "Aqui entrará o cabeçalho!"}}</h1>
    </div>
    
<script>
    new Vue({
        el: '#app'
    }) 
</script>
</body>
</html>

Em seguida abra o arquivo usando o seu navegador e deverá ver uma tela semelhante a tela abaixo:

Examinando o código vemos que a instalação do Vue.js foi feita na linha em destaque (sexta linha) a partir de uma rede de distribuição de conteúdo.

Referência:

https://vuejs.org/v2/guide/installation.html

Vue.js Básico

No decorrer do tutorial iremos apresentar os conceitos básicos do Vue.js de forma prática a medida em que alterarmos o código original acima e constatarmos as mudanças ocorridas na página do browser.

Instância

Qualquer aplicação do Vue.js é iniciada através da criação de uma nova instância, o que é feito por meio da função Vue.

Esta função receberá como parâmetro um objeto contendo opções que irão determinar o comportamento desejado para a instância. Desta forma, o trecho abaixo extraído do código que estamos examinando:

new Vue({
        el: '#app'
    })

Cria uma instância do Vue com um parâmetro objeto que contém somente a opção el, esta serve para relacionar a instância que está sendo criada com um elemento do DOM.

Assim, a instância será montada e poderá ser referenciada usando este elemento, o qual, por sua vez, poderá ser um seletor CSS ou um Elemento HTML.

Referências:

https://vuejs.org/v2/guide/instance.html

https://vuejs.org/v2/api/#Options-Data

Referenciando o Elemento(el)

Prosseguindo, no código vemos o trecho abaixo que monta a instância do Vue.js em nossa página HTML. Para isto é utilizado o id=”app” (sem a cerquilha, sustenido ou hashtag) do elemento definido na criação da instância conforme descrito no item anterior.

<div id="app">
   <h1>{{ header ? header : "Aqui entrará o cabeçalho!"}}</h1>
</div>

Double mustache

No código acima vemos também o elemento de interpolação representado pelas chaves duplas, {{}}, também chamadas de double mustache.

Exte é o tipo mais simples de data binding presente no Vue.js e baseia-se na renderização de um template que irá gerar a página HTML correspondente.

Em termos gerais, durante a renderização a expressão que estiver entre as chaves será avaliada e seu resultado será mesclado ao código HTML.

Assim, no código acima é avaliada a expressão ternária que verifica se existe a variável header e retorna seu valor neste caso. Caso contrário, ou seja, se a variável não existir ou se o valor da mesma for nulo, é devolvida a string: “Aqui entrará o cabeçalho”.

Usando este tipo de interpolação também é possível executar comandos JavaScript de linha única. Para exemplificar isto vamos fazer a seguinte modificação no código:

<h1>{{ header ? header : "Aqui entrará o cabeçalho!"}}</h1>
<h2>Data de hoje: {{ Date() }}</h2>

Recarregue a página no browser e agora deverá ser exibida a data de hoje completa com horário e dia da semana. Após isto pode retirar ou comentar esta linha e voltar ao código original.

Prosseguindo em nosso estudo vamos agora definir a variável header, para isto em nosso código original faça as alterações destacada abaixo:

var meuapp = new Vue({
        el: '#app',
        data: {
            header : 'Meu cabeçalho'
        }
    })

Examinando o código acima vemos que foram feitas duas mudanças. A primeira delas (trecho var meuapp = ) servirá para que possamos usar o console do browser para alterar variáveis de nossa instância Vue.

A segunda alteração (definição de data: ) cria e define um valor para a variável header,  a qual irá armazenar o cabeçalho de nossa página exemplo.

Feitas as alterações, recarregue a página no browser e deverá ver uma tela semelhante a ilustrada abaixo:

Agora, devido ao fato de a variável header ter sido definida, a expressão ternária retornará o valor desta variável o qual será mesclado ao código html produzido pela renderização.




Prosseguindo nosso tutorial de Vue.js, vamos agora fazer duas experiências com a reatividade do Vue.js, para isto entre no console de seu browser (CTRL+SHIFT+I).

Agora, no console, digite a seguinte linha de comando seguida de ENTER:

meuapp.$data.header = "Outro cabeçalho !"

Observe a tela do browser, esta deverá ter sido atualizada e o cabeçalho da página agora exibe o texto “Outro cabeçalho !”.

Como segunda experiência digite a linha de comando abaixo:

meuapp.$data.header = ""

Neste caso atribuiremos um valor de string vazia que é interpretado como um valor nulo pela expressão ternária e, em consequência, teremos no browser a alteração do texto do cabeçalho conforme ilustrado abaixo:

v-html

Os dados interpolados pelas chaves duplas serão interpretados como texto simples, e não como HTML. Contudo nos templates do Vue.js, pode ser usada a diretiva v-html para que o framework os entenda como código html. Para exemplificar isto faça a seguinte alteração na página html que estamos codificando:

<div id="app">
        <h1 >{{ header ? header : "Aqui entrará o cabeçalho!"}}</h1>
        <h2> Cabeçalho HTML: <span v-html="header"></span></h2>
    </div>

Em seguida, recarregue a página, acesse o console e digite a linha de comando abaixo:

meuapp.$data.header = "<hr><i>Cabeçalho</i>"

O resultado deverá ser semelhante ao ilustrado na figura abaixo:

Na figura podemos ver que no primeiro caso, uso de chaves duplas para interpolação, o Vue.js interpretou o valor de header como texto simples.

No segundo caso, ou seja, usando a diretiva v-html, o valor de header foi interpretado pelo framework como código html.

Atenção! Renderizar código html dinamicamente é perigoso, pois possibilita um ataque de XSS e outros ataques do tipo injeção. Assim o recomendado é que não use a interpolação html, porém caso a utilize faça isto apenas para conteúdo confiável e devidamente sanitizado e nunca para conteúdo fornecido pelos usuários.

Feitos os testes acima você pode excluir ou comentar a linha que foi inserida, de forma a voltar ao código original.

v-bind

A interpolação usando chaves duplas não funciona para atributos dos elementos HTML. Desta forma para realizar o data binding e definir o valor de atributos dos elementos html, devemos usar a diretiva v-bind. Vamos agora examinar um exemplo, para isto faça as alterações destacadas abaixo em nosso código original:

<div id="app">
        <h1 >{{ header ? header : "Aqui entrará o cabeçalho!"}}</h1>
        <a v-bind:href="url" target="_blank">Clique AQUI</a>
    </div>  
<script>
    var meuapp = new Vue({
        el: '#app',
        data: {
            header : 'Meu cabeçalho',
            url: "http://www.google.com"
        },

Com as mudanças acima incluímos um link através da tag <a> e definimos uma variável url que corresponderá ao atributo href desta tag. Para ligar a variável url ao atributo usamos a diretiva v-bind.

Após as alterações recarregue a página no browser e observe que a página que foi renderizada possui um link que é definido dinamicamente.

Além disso, da mesma forma que fizemos antes, é possível utilizar o console do browser para definir a url que será ativada ao clicar no link.

Na tela abaixo vemos uma ilustração do que deverá ser mostrado no browser:

Two-way binding

Até agora vimos somente exemplos de one-way data binding, ou seja, casos em que alterações no modelo, dados, ou variáveis, repercutem em alterações na interface.

Veremos a seguir como o Vue.js possibilita que seja implementada a two-way binding, pela qual alterações na interface acarretarão alterações nos dados.

v-model

Para fazer uso do two-way data binding devemos empregar a diretiva v-model. Como exemplo deste uso, faça a seguinte alteração em nosso código:

<div id="app">
        <h1 >{{ header ? header : "Aqui entrará o cabeçalho!"}}</h1>
        <a v-bind:href="url" target="_blank">Clique AQUI</a>
        <input type="text" v-model="header">
    </div>

Esta modificação incluiu um campo de input e associou o mesmo, através do v-model, com a variável header.

Para fins de teste, recarregue a página e digite algum texto no campo de input, observe então que o cabeçalho da página é alterado conforme você digita.

Considerando que este cabeçalho é na verdade o conteúdo da variável header, constatamos que uma mudança na interface, ocasionada pela digitação do texto, alterou o valor dos dados, no caso o valor da variável header.




Para verificar que as alterações funcionam da forma contrária, two-way binding, utilize o console do browser para alterar o valor da variável header. Verá que, ao fazer isto, será alterado também o valor do texto no campo de input, ou seja, alterando os dados ocorre também a alteração na interface.

Acima está ilustrada a tela que deverá ser exibida durante os testes com o v-bind.

v-for

Esta diretiva implementa um loop na renderização feita pelo Vue.js, para exemplificar seu funcionamento vamos primeiro definir um vetor contendo os elementos de uma lista de afazeres. Para isto modifique o código inserindo as linhas em destaque abaixo:

var meuapp = new Vue({
        el: '#app',
        data: {
            header : 'Meu cabeçalho',
            url: "http://www.google.com",
            afazeres: [ 
                "comprar pão",
                "escrever um livo",
                "arrumar o armário"
            ]
        }

Em seguida iremos utilizar a diretiva v-for para renderizar os elementos do array produzindo a página html correspondente. Para isto faça as seguintes alterações no código:

<div id="app">
        <h1 >{{ header ? header : "Aqui entrará o cabeçalho!"}}</h1>
        <a v-bind:href="url" target="_blank">Clique AQUI</a>
        <input type="text" v-model="header">
        <div id="lista-todo">
            <h3>Afazeres de hoje</h3>
            <ul>
                <li v-for="afazer in afazeres">{{afazer}}</li>
            </ul>
        </div>
    </div>

Examinado as alterações podemos ver que inicialmente foi criada uma div, ela será usada mais adiante neste texto para ilustrar outras funcionalidades do framework e por este motivo já atribuímos a ela um id.

Em seguida definimos um cabeçalho, que será o título da lista, e a lista propriamente dita. Finalmente, usando a diretiva v-for incluímos o código que irá renderizar cada elemento da lista, obtendo seus valores do array afazeres que definimos anteriormente.

Feitas as alterações, recarregue a página e deverá ver em seu browser uma tela semelhante a que está ilustrada abaixo:

Eventos

No Vue.js os eventos ocorridos na interface dos usuários podem ser associados aos métodos de uma instância.

methods

Usando o Vue.js é possível definir métodos que serão executadas em resposta a eventos específicos. Os métodos são escritos em JavaScript e podem utilizar todos os recursos disponíveis nesta linguagem.

O trecho de código destacado abaixo implementa um método em nosso exemplo de aplicação Vue.

var meuapp = new Vue({
        el: '#app',
        data: {
            header : 'Meu cabeçalho',
            url: "http://www.google.com",
            afazeres: [ 
                "comprar pão",
                "escrever um livo",
                "arrumar o armário"
            ],
            exibeLista: true
        },
        methods: {
            showLista: function () {
                this.exibeLista = !this.exibeLista
                this.exibeLista 
                 ? document.getElementById("botao-lista").innerHTML = "Esconde lista"
                 : document.getElementById("botao-lista").innerHTML = "Mostra a lista"
            }
        }
    })

Examinando o trecho de código acima vemos que foi criada a variável exibeLista do tipo boolean e que foi definida inicialmente como true.

Em seguida temos a definição de um método com o nome showLista. Este método irá alterar o valor da variável exibeLista e de acordo com este valor o texto do botão cuja id é botao-lista.




Observe que para acessar a variável interna é necessário utilizar a palavra-chave this, indicando uma referência explícita a variável presente na instância do Vue.

Vale destacar também o uso da função getElementById para obter uma referência ao botão e acessar/alterar diretamente seu atribuo innerHTML que, neste caso, corresponde ao texto contido no botão.

Para que este código funcione necessitamos fazer mais algumas modificações no restante do arquivo, veremos quais no próximo item onde apresentaremos outro recurso do Vue.js a diretiva v-on.

Referências:

https://developer.mozilla.org/pt-BR/docs/Web/API/Document/getElementById

https://www.w3schools.com/jsref/prop_html_innerhtml.asp

v-on

No Vue.js temos a diretiva v-on que é utilizada para associar os event listener do DOM aos métodos de nossa instância Vue, estes serão executados quando o evento correspondente for disparado. Para um exemplo de como usar o v-on digite o código destacado abaixo:

<div id="app">
        <h1 >{{ header ? header : "Aqui entrará o cabeçalho!"}}</h1>
        <a v-bind:href="url" target="_blank">Clique AQUI</a>
        <input type="text" v-model="header">
        <div id="lista-todo" v-if="exibeLista">
            <h3>Afazeres de hoje</h3>
            <ul>
                <li v-for="afazer in afazeres">{{afazer}}</li>
            </ul>
        </div>
        <button id="botao-lista" v-on:click="showLista">Esconde lista</button>
    </div>

Este código complementa o que foi fornecido anteriormente criando um botão com o id de botao-lista e associa o evento click deste botão, usando a diretiva v-on:click, ao método showLista que foi definido no código anterior. Desta forma, quando ocorrer um clique no botão será disparada a execução do método showLista.

v-if

Outro recurso presente no Vue.js é a renderização condicional, isto é obtido pelo uso da diretiva v-if. No código acima, vemos que na linha que define uma div contendo a lista de afazeres foi incluída esta diretiva.

Assim, o Vue.js passará a exibir esta div de acordo com o valor da variável exibeLista, exibindo a lista quando este valor for true e a escondendo quando o valor for false.

Após esta última alteração podemos recarregar a página no browser, o qual deverá exibir uma tela semelhante a ilustrada abaixo:

O comportamento esperado é que ao clicar no botão “Esconde Lista” a lista de afazeres desapareça da tela e o botão passe a exibir “Mostra a lista”.

Um novo clique sobre o botão deverá exibir a lista e voltar o texto do botão ao valor anterior.

Computed properties

Este recurso do Vue é utilizado para realizar transformações e cálculos nos dados e variáveis de uma instância. Entre as possibilidades de uso deste recurso podemos citar: validação de entrada de dados, formatação de valores, cálculo de atributos, entre outros.

Em nosso exemplo iremos criar uma computed property que corresponderá ao cabeçalho de nossa página formatado para letras maiúsculas. Para fazer isto insira as alterações destacadas abaixo em nosso código original:

...
       methods: {
            showLista: function () {
                this.exibeLista = !this.exibeLista
                this.exibeLista
                 ? document.getElementById("botao-lista").innerHTML = "Esconde lista"
                 : document.getElementById("botao-lista").innerHTML = "Mostra a lista"
            }
        },
        computed:{
            headerUpCase (){
                return this.header.toLocaleUpperCase();
            }
        },
...

Agora nossa instância Vue dispõem da propriedade headerUpCase que pode ser referenciada no template da mesma forma que referenciamos uma variável.

Para fins de teste podemos fazer em nosso código a seguinte alteração:

...
        <h1 >{{ header ? header : "Aqui entrará o cabeçalho!"}}</h1>
        <h2>{{ headerUpCase }}</h2>
        <a v-bind:href="url" target="_blank">Clique AQUI</a>
        <input type="text" v-model="header">
    ...


Em seguida recarregar a página no browser para obter uma tela semelhante a que segue:

Atenção !

Uma das fontes mais comuns de erros nas aplicações Vue é utilizar comandos nas computed properties para alterar os valores originais de variáveis da instância. Assim, tenha em mente que elas devem ser usadas para transformar os dados originais, porém sem alterá-los, desta forma é altamente recomendável que as computed properties manipulem cópias das variáveis originais e não diretamente seus valores os quais, na medida do possível, devem ser mantidos inalterados.

Uma boa prática é utilizar os métodos para alterações nos dados e as computed properties para transformação e formatação destes.




V-Dev-tools

Finalizando este tutorial de Vue.js que equivaleu a um curso rápido de introdução, vamos mencionar o Vue.js Devtools que é um plugin utilizado para depuração e testes dos aplicativos Vue. Este plugin está disponível para Chrome e Firefox e para instalá-lo basta procurar no Goole e seguir as instruções conforme o browser que estiver utilizando.

Serve para interagirmos com nossa instância Vue.js diretamente no browser, é uma excelente ferramenta que pode ser usada para testes e debug das aplicações Vue.

Além disso, usando o dev-tools não é mais necessário que a instância do Vue seja atribuída a uma variável para que tenhamos acesso às suas variáveis internas.

Nota:

Ao utilizar o DevTools no Chrome para depurar páginas carregadas no browser com o protocolo file: ou arquivo:, será necessário entrar na configuração do plugin e habilitar a opção ilustrada abaixo:

Caso não faça esta configuração o Chrome irá habilitar o Vue Devtools apenas quando a página estiver sendo acessada por meio de um servidor web com o protocolo http, e não funcionará da forma que estamos usando até agora que é abrir a página em modo arquivo diretamente no browser. Após instalar o DevTools você poderá voltar o código:

var meuapp = new Vue({
        el: '#app',

Ao original, que é:

new Vue({
   el: '#app',

Assim, retirando a referência à variável meuapp, pois esta não é necessária e foi criada somente para que, usando o console do browser, tivéssemos acesso às variáveis de nossa instância do Vue.

Como o Vue.js Devtools já faz isso para nós, não necessitamos mais fazê-lo manualmente.

Leia também

Vue.js no Laravel
Tutorial instalação – Iniciando com o Laravel parte 1
eBook chatbot usando Laravel Botman e Dialogflow