Iniciando um projeto JavaScript em 2017

Como sabemos, o cenário atual do JavaScript, está uma bagunça daquelas, que só quem fez sabe onde as coisas estão guardadas. Isso, aquela que você faz no seu quarto e ninguém, a não ser você, sabe o local das coisas.

Então, para ajudar vocês a entender essa bagunça, eu vou mostrar algumas coisas que podem ser muito úteis, para quem ainda não está por dentro desse JS WORLD (não, não é Jurassic World).

Pré-Requisitos

  • Conhecimento básico de HTML e Javascript
  • Node

Escolha um bom editor de textos ou IDE

Sempre é bom que você tenha consigo, ferramentas de trabalho que o ajudem a alcançar o seu objetivo. Nesse caso, nosso objetivo é criar um workspace para usar JS(es6) + Angular.

Minha escolha

VSCODE: Pra mim, hoje, o editor de textos mais completos, é o Visual Studio Code. É leve, direto, tem ferramentas muito úteis e tem inúmeras extensões que podem me ajudar.

Comece a gostar da command line

A maior parte do setup de um novo projeto, vai acontecer na command line(cmd/powershell/bash), então, se você não tem costume de procurar a definição dos comandos usados, é bom começar a desenvolve-lo, pois, essa é uma das formas mais fáceis de entender, o que tal comando irá fazer.

Não confie cegamente nas documentações, até porque, geralmente elas são atualizadas por pessoas, assim como eu e você. E diferente das máquinas, nós, esquecemos de algumas coisas, certo? eu não

Vamos lá

Pra começar, crie uma pasta. Você decide o nome, eu deixo. Eu vou chamar a minha de introducao-js.

mkdir introducao-js
cd introducao-js

Inicie um “projeto” do npm (node package manager), usando o seguinte comando.

npm init

Dica: Usem o Yarn ao invés do Npm. Ele é mais rápido e os seus métodos são mais práticos e sucintos.

Preencha as informações requisitadas, e no final desse “quiz” você verá que foi gerado um arquivo package.json. Se você não souber o que preencher em alguns campos, simplesmente aperte enter e prossiga.

Certo! Agora temos um projeto JS (node).

Decida qual framework vai usar

Claro, não é obrigatório você usar um framework, mas, a não ser que você goste de sofrer, creio que um framework, que faça o trabalho “sujo” de cuidar da compatibilidade do seu código, cai bem, não?
Vou estar usando Angular 1.x e o servidor Express nesse mini tutorial. Nosso objetivo vai ser fazer uma lista de tarefas.

Vamos criar uma pasta chamada src para manter o código da aplicação. Criaremos também, um arquivo, index.js para iniciar o nosso servidor, assim, poderemos ver a nossa aplicação.

Mão na massa

Primeiro, vamos criar todos os arquivos necessários para fazer o nosso aplicativo começar a funcionar. Vamos deixar para escrever o código neles daqui à pouco.

Esta é a estrutura inicial do nosso projeto.

.
├── index.js # Inicializador do nosso server
├── package.json  # O arquivo criado pelo 'npm init'
└── src
    ├── css
    │ └── app.css # folha de estilos do nosso app
    ├── index.html # página inicial
    └── js
      └── app.js # Aqui vai o código da aplicação

3 diretórios, 5 arquivos

Criando o servidor

Vamos usar o Express para nos ajudar com essa tarefa.

//importamos o módulo do express
const express = require("express");

function meuAngularApp() {
    // criamos nosso servidor do express
    // qualquer dúvida que você tenha de como usa-lo melhor
    // acesse a referência da API do express
    // http://expressjs.com/pt-br/4x/api.html
    var app = express();

    // a função use() ela serve para permitir que você use
    // um controlador de requisições feitas em seu servidor
    // estaremos usando a função express.static() para gerar 
    // um servidor de conteúdo estático na pasta 'src'
    // para podermos acessar na url '/'
    app.use(express.static("./src", {
        extensions: [
            "html",
            "htm",
            "js",
            "css"
        ]
    }));

    // criamos outro controlador para as nossas 
    // bibliotecas. Assim não precisamos usar um site externo
    // para carregar nossas bibliotecas
    app.use(express.static("./node_modules", {
        extensions: [
            "js",
            "css"
        ]
    }));

    // a função listen() faz com que o servidor espere
    // por requisições na porta informada
    // nesse caso a porta 9000
    var porta = (process.env.PORT || 9000);
    app.listen(porta, function (erro) {
        // se acontecer algum erro ao ligar
        // o erro vai ser mostrado e a aplicação para
        if (erro)
            throw erro;

        // Exibimos no console que o servidor está ligado
        // e pronto para receber requisições
        console.log("Servidor iniciado em http://127.0.0.1:" + porta);
    });

    return app;
}

// Aqui é exportado o módulo do nosso servidor
// caso você queira saber mais sobre módulos do Node
// procure por "CommonJS Modules"
module.exports = meuAngularApp();

Creio que não tem muita complexidade nesse script para gerar o server, até porquê, o Express nos permite criar um servidor muito bem estruturado, com poucas linhas de código simples e fácil de entender.

Pagina do app

Os comentários abaixo explicam de uma forma mais direta o código.

<!DOCTYPE html>
<!--
 Estamos definindo que o aplicativo do angular à ser usado
 é o 'listaTarefasApp' e que iremos usar a diretiva
 'ng-strict-di'. Essa diretiva serve para 'obrigar'
 o desenvolvedor à sempre usar a injeção escrita
 das dependências do controller.
 -->
<html lang="pt-BR" ng-app="listaTarefasApp" ng-strict-di>

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <title>Johnny A. Santos - Lista de Tarefas</title>
  <!-- Fontes para facilitar a leitura -->
  <link href="https://fonts.googleapis.com/css?family=Open+Sans|Ubuntu" rel="stylesheet">

  <!-- Estilo -->
  <link href="/css/app.css" rel="stylesheet">
</head>

<body ng-controller="listaTarefasController as vm">
  <!-- Aqui criamos uma div para conter todos os objetos da nossa lista -->
  <div class="conteiner-lista">
    <h1>Lista de Tarefas</h1>
    <!--
      ng-submit permite que você escreva uma expressão para ser avaliada e executada
      no evento de envio do formulário em que se encontra.
      -->
    <form ng-submit="vm.novaTarefa()" class="nova-tarefa">
      <input placeholder="Criar uma tarefa" class="titulo" required ng-model="vm.tarefaObj.titulo" />
      <button class="botao botao-nova-tarefa" type="submit">Nova tarefa</button>
    </form>
    <!--
      Div que será repetida pela diretiva ng-repeat do Angular
      para cada item no nosso array dentro do controller
      -->
    <div class="objeto-lista" ng-repeat="tarefa in vm.tarefas">
      <!--
        Estou usando o ng-if para "economizar" nos *watchers* do Angular
        ng-class faz a adesão da classe 'item-finalizado' quando o meu objeto
        `tarefa` do escopo local tem a propriedade `concluida` como `true`
        o ng-cloak serve para esconder os elementos do html até que o Angular
        tenha carregado por completo
       -->
      <div class="item-lista" ng-if="!tarefa.editando" ng-cloak ng-class="{ 'item-finalizado': tarefa.concluida }">
        <!--
          A diretiva ng-bind faz com que o valor dentro do meu `span` seja o da propriedade
          `titulo` dentro do objeto `tarefa`. Os `::` (dois pontos) são para informar que esse
          é um bind único, e que só acontecerá essa "passagem" de valores para o meu span
          só ocorra uma vez.
          Dica: Eu prefiro sempre usar o ng-bind ao {{}}, porque ele só é avaliado quando 
          o Angular termina de carregar, sem mostrar o código no inicio do app.
         -->
        <span class="titulo-lista" ng-bind="::tarefa.titulo" ng-click="vm.finalizar(tarefa)"></span>
        <div class="botoes-conteiner">
          <!--
            A diretiva ng-click permite que você escreva uma expressão, podendo
            usar as variáveis do escopo local ou global do Angular,
            que será avaliada dentro do evento de clique do botão.
          -->
          <button class="botao botao-edicao" ng-click="vm.editar(tarefa)">Editar</button>
          <button class="botao botao-remocao" ng-click="vm.remover(tarefa)">Remover</button>
        </div>
      </div>

      <form ng-submit="vm.salvar(tarefa)" class="item-lista item-edicao-lista" ng-if="tarefa.editando" ng-cloak>
        <input ng-model="tarefa.titulo" />
        <button type="submit" class="botao botao-salvar">Salvar</button>
      </form>
    </div>
  </div>
  <small class="footer">2017 - <a href="https://johnnyasantos.com" target="_blank">Johnny Anderson dos Santos</a></small>
</body>
<!-- Scripts podem ir no final do HTML para ajudar no carregamento -->
<script src="/angular/angular.js" defer></script>
<script src="/js/app.js" defer></script>

</html>

Finalmente o JavaScript

Novamente, vamos direto ao código. Até por quê, como já dizia Linus Torvalds

Talk is cheap, show me the code!

// criamos nosso aplicativo angular
var app = angular.module("listaTarefasApp", []);

// vamos então, definir um controlador (controller)
// para nossa view (a pagina) do nosso aplicativo
app.controller("listaTarefasController", listaTarefasController);

/**
 * Controlador da nossa aplicação
 * @param {Object} $log logger padrão do Angular
 */
function listaTarefasController(
    $log
) {
    //uma referência para ajudar no entendimento
    var vm = this;

    //lista de tarefas
    vm.tarefas = [];

    function inicializarTestes() {
        var hw = criarTarefa();
        hw.editando = true;
        hw.titulo = "Hello world!";

        vm.tarefas.push(hw);

        var om = criarTarefa();
        om.titulo = "Olá Mundo!"
        vm.tarefas.push(om);
    }
    inicializarTestes();


    //objeto para criação de novas tarefas
    vm.tarefaObj = criarTarefa();

    /**
     * Cria um novo objeto de tarefa
     * @returns {Tarefa}
     */
    function criarTarefa() {
        return new Tarefa(vm.tarefas.length);
    }

    /**
     * Adiciona uma nova tarefa a lista
     */
    function novaTarefa() {
        $log.debug("Criando nova tarefa.");

        vm.tarefas.push(vm.tarefaObj);

        vm.tarefaObj = criarTarefa();
    }
    //desta forma, expomos essa função ao objeto gerado pelo nosso controller
    //diferentemente da função criarTarefa que não é exibida publicamente 
    vm.novaTarefa = novaTarefa;

    /**
     * Finaliza a edição da tarefa
     * @param {Tarefa} tarefa 
     */
    function salvar(tarefa) {
        $log.debug("Salvando item: %s.", tarefa.titulo);
        tarefa.editando = false;
    }
    vm.salvar = salvar;

    /**
     * Finaliza a edição da tarefa
     * @param {Tarefa} tarefa 
     */
    function remover(tarefa) {
        $log.debug("Removendo item: %s.", tarefa.titulo);

        vm.tarefas = vm.tarefas.filter(function (t) {
            return t.id !== tarefa.id;
        });
    }
    vm.remover = remover;

    /**
     * Coloca uma tarefa em edição
     * @param {Tarefa} tarefa 
     */
    function editar(tarefa) {
        $log.debug("Iniciando edição do item: %s.", tarefa.titulo);
        tarefa.editando = true;
    }
    vm.editar = editar;

    /**
     * Troca o status da tarefa
     * @param {Tarefa} tarefa 
     */
    function finalizar(tarefa) {
        $log.debug("Alterando o status do item: %s.", tarefa.titulo);
        tarefa.concluida = !tarefa.concluida;
    }
    vm.finalizar = finalizar;

    //retornamos o nosso objeto do controller
    return vm;
}

listaTarefasController.$inject = [
    "$log"
];


/**
 * Nosso construtor do nosso objeto de tarefa
 * @param {number} id Id da tarefa
 */
function Tarefa(id) {
    this.id = id;
    this.titulo = '';
    this.editando = false;
    this.concluida = false;

    return this;
}

Acessem o exemplo

O código é aberto, e está no GitHub, quando vocês verem o código e a estrutura do projeto, irão entender melhor o seu funcionamento.

Fiz também um exemplo “ao vivo” do nosso pequeno projetinho JS.
Acesse-o aqui https://introducao-js.herokuapp.com/

Qualquer erro encontrado, sugestão, ou ideia, crie um issue no GitHub.

Espero que eu tenha sido claro.

Até a próxima 🙂

Anúncios

Um comentário sobre “Iniciando um projeto JavaScript em 2017

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s