Categorias
Tutoriais Web

Variáveis e funções com ECMAScript 2015

ECMAScript 2015 é nova especificação do JavaScript antes chamado de ECMAScript 6, por uma padrão de conversão e buscando implementações menores em pequeno prazo. Lembrando que esses recursos nem todos os browser rodam, o ideal é utilizar uma ferramenta para compilar seu código para browsers antigos, um dos mais utilizados é o Babel, ele possui um handbook em português que mostra instalação e como usar:

https://github.com/thejameskyle/babel-handbook/blob/master/translations/pt-BR/user-handbook.md

Boa parte dos exemplos eu rodei no Chrome sem precisar do babel, nesta página(ECMAScript 6 compatibility table) você tem uma tabela detalhada do suporte de cada browser. Para um projeto em produção é necessário o uso do babel. Agora voltando ao ECMAScript, ela vem com uma série de novidades, já mostrei alguns dos novos recursos nos posts sobre REACT, mas não entrei em detalhes neste post vou listar algumas das novidades.

Declarando variáveis

let

let é utilizado para declarar variáveis dentro de um escopo menor comparado ao var que tem um escopo global ou relacionado a funções, com o let o escopo pode ser limitado por blocos menores if, else, for e while.

const

const como em outras linguagens o permite nos criarmos variáveis read-only, constantes nos ajudam a criar códigos mais legíveis, exemplo quando lemos o seguinte código:

function doSomething(num) {
  if(num < 5) {
    //doSomething
  }

  for(var i = 0; i < 5; i++) {
    //doSomething
  }
}

Não temos idéia o que é o número 5, apenas um fator na condicional, se mudarmos para o seguinte código:

function doSomething(num) {
  const MAX_PRODUCTS = 5;
  
  if(num < MAX_PRODUCTS) {
    //doSomething
  }

  for(var i = 0; i < MAX_PRODUCTS; i++) {
    //doSomething
  }
}

Agora com as modificação batemos o olho sabemos que os loops estão limitados por um número máximo de produtos. Esse valor é escrito apenas uma vez, ele não pode ser alterado após ser definido. Por um padrão de escrita de código todas as constantes precisa ser escritas em uppercase.

Funções

Surgiram novas funcionalidades super úteis relacionadas a funções com ECMAScript 2015. A primeira delas, valores default na assinatura da funções. Um problema básico é acesso a variáveis undefined, temos um tratamento comum para isso da seguinte forma:

function listProducts(listOfProducts) {
  var products = typeof listOfProducts !== 'undefined' ? listOfProducts : [];
  var total = products.length;
  //do something
}

Com nova definição de EcmaScript 2015 podemos criar valores default sem precisar de um tratamento especial como a versão anterior da seguinte forma:

function listProducts(listOfProducts = []) {
  let total = listOfProducts.length;
  //do something
}

Nomeando parâmetros

Uma nova funcionalidade, agora é possível nomear parâmetros como isso é útil, no exemplo abaixo:

function setProduct(newProduct = {}) {
  product.name = newProduct.name;
  product.price = newProduct.price;
  product.category = newProduct.category;
}

Exemplo acima contornamos o problema do parâmetro “undefined” mas se os atributos não existirem nosso código irá disparar um erro.

function setProduct({name, price, category} = {}) {
  product.name = name;
  product.price = price;
  product.category = category;
}

Nomeando parâmetros, além do código ficar mais legível, não caímos nos problemas de atributos inválidos.

Rest Params

Outro novo recurso do ECMAScript 2015 é possível passar um array de parâmetros como argumento, como isso funciona, por exemplo, temos uma função de produtos relacionados onde podemos exibir, um, dois ou três produtos:

showRelacionados(“produto-1”);

showRelacionados(“produto-1”, “produto-2”, “produto-3”);

showRelacionados(“produto-1”, “produto-2”);

Você precisa passar um número x de argumentos que sempre variam, nunca é uma quantidade exata. Com parâmetros rest, permite definir que a função espera um array de argumentos.

function showRelated(...related) {
  for(let i in related ) {
    console.log(related[i]);
  }
}

showRelated("produto-1", "produto-2", "produto-3");

Além dos “…” na assinatura da função, podemos adicionar na chamada da função mas ela tem uma funcionalidade diferente quando acionamos a função, neste caso ela quebra os parâmetros do objeto em vários argumentos. Exemplo temos o objeto

produto.nome = “Prato”;
produto.preco = 20;
produto.categoria = “casa”;

adicionaProduto(…produto);

A função “adicionaProduto” irá receber 3 parâmetros(nome, preco e categoria).

Arrow function

Arrow function além de simplificar a escrita de funções ela mantém o escopo de quem invoca a função útil quando estamos tratando, também chamado de “lexical binding” ele cria um escopo de quem o define e não de onde ele roda, outro ponto a Arrow functions sempre são anônimas. Sua síntaxe é simples:

([parametro], [parametro]) => {
   //código que será executado na chamada da função
}

Exemplo temos um código sem arrow function:

var categorias =  ["casa", "jardim", "praia"];

categorias.map(function(prop) {
  console.log(prop);
});

Com arrow function ele fica da seguinte forma:

var categorias =  ["casa", "jardim", "praia"];

categorias.map(prop => {
  console.log(prop);
});

Apenas uma chamada mas imagine isso sendo repetido várias vezes no dia, mas outra vantagem é a questão do escopo um problema comum é perder o escopo quando você codando alguma funcionalidade exemplo:

function Clock() {
  this.time = 10; 
  
  setInterval(function count() {
    this.time++;
    console.log(this.time, this);
  }, 1000);
};

var c = new Clock();

Criamos um objeto tipo Clock, mas ele tem um problema quando usamos o console dentro do setInterval por exemplo o escopo do setInterval é global nesse momento o this não é o clock e sim o objeto Window. Claro que podemos resolver esse problema criando uma variável self para para o clock e guardar o this(clock) dentro dessa variável outra solução seria usar o arrow function:

function Clock() {
  this.time = 10; 
  
  setInterval( () => {
    console.log(++this.time, this);
  }, 1000);
};

var c = new Clock();

Vamos ficando por aqui o próximo post sobre ECMA irei falar sobre objetos e classes.

Categorias
Geral Tutoriais Web

Pensando em React

Um dos pontos importantes na hora de aprender React é trabalhar no modo que ele espera a “componentização” do conteúdo, esse processo inicia a partir da construção dos mocks.

Passo 1 – Iniciando como um mock

Imagine que você tem a seguinte tela:

Como criaríamos componentes com esse mock?

No caso acima temos uma coleção de portfólio, um componente job, com: foto, descrição, url, empresa, Design, e tecnologias. Vamos considerar que toda esta coleção está em um JSON:

[{"nome": "job 1", "url": "http://fellyph.com.br/", "empresa": "Empresa 1", "designer": "Artista 1", "tecnologias": ["HTML", "CSS", "JS"]},
{"nome": "job 2", "url": "http://fellyph.com.br/", "empresa": "Empresa 2", "designer": "Artista 2", "tecnologias": ["HTML", "CSS", "JS"]},
{"nome": "job 3", "url": "http://fellyph.com.br/", "empresa": "Empresa 3", "designer": "Artista 3", "tecnologias": ["HTML", "CSS", "JS"]},
{"nome": "job 4", "url": "http://fellyph.com.br/", "empresa": "Empresa 4", "designer": "Artista 4", "tecnologias": ["HTML", "CSS", "JS"]},
{"nome": "job 5", "url": "http://fellyph.com.br/", "empresa": "Empresa 5", "designer": "Artista 5", "tecnologias": ["HTML", "CSS", "JS"]},
{"nome": "job 6", "url": "http://fellyph.com.br/", "empresa": "Empresa 6", "designer": "Artista 6", "tecnologias": ["HTML", "CSS", "JS"]}]

E o nosso componente básico é o seguinte:

Seguindo essa estrutura inicialmente nosso componentes com suas hierarquias serão os seguintes:

  • PortifolioList
    • PortifolioItem

Por que falamos em hierarquias? No caso podemos ter componentes que carregam outros componentes, mas isso não impede de outros elementos carregarem o mesmo componente.

Passo 2 – Construindo uma versão estática com React

No post anterior, trabalhamos com “React.createClass” nesse tutorial vamos utilizar um cara chamado “React.Component” ele trabalha de uma forma diferente com ele criamos um classe que estendem de React.Component lembrando que para trabalhar com classes precisamos do babel para rodar o nosso ECMAScript 2015 e o React. Vamos começar pelo item mais básico o PortfolioItem, primeiramente considerando o mock que construímos o seguinte HTML:

<article class="job">
  <h4 class="title">Blog elo7</h4>
  <ul class="fetures">
    <li><a href="#" target="_blank" alt="site">linkdosite.com.br</a></li>
    <li>Empresa: Elo7</li>
    <li>Tecnologias: HTML5, CSS3, WordPress</li>
  </ul>
</article>

Agora vamos passar o nosso HTML para o um componente:

class PortfolioItem extends React.Component {
  render() {
    return (
      <article className="job">
        <h4 className="title">Blog elo7</h4>
        <ul className="fetures">
          <li><a href="#" target="_blank" alt="site">linkdosite.com.br</a></li>
          <li>Empresa: Elo7</li>
          <li>Tecnologias: HTML5, CSS3, WordPress</li>
        </ul>
      </article>
    )
  }
}

Apenas adicionei o PortfolioItem com HTML estático só para mostrar como funciona o React.Component, notem que trocamos a propriedade class por className isso é necessário para não termos conflitos com a palavra reservada class, mas as informações estão estáticas precisamos carregar as informações dinamicamente, a cada chamada do componente ele precisa ter uma informação diferente, então vamos lá:

class PortfolioItem extends React.Component {
  render() {
    return (
      <article class="job">
        <h4 class="title">{this.props.nome}}</h4>
        <ul class="fetures">
          <li><a href="#" target="_blank" alt="site">{this.props.site}</a></li>
          <li>Empresa: {this.props.empresa}</li>
          <li>Tecnologias: {this.props.tecnologias}</li>
        </ul>
      </article>
    )
  }
}

No código acima utilizamos o “{}” para especificar que é uma variável dinâmica this.props. acessa os parâmetros que foram passado para o componente, nesse caso chamamos o componente da seguinte forma:

<PortfolioItem nome={job.nome} site={job.site} empresa={job.empresa} tecnologias={job.tecnologias} />

Assim o atributo nome passado no componente acessamos dentro do componente {this.props.nome}, nosso exemplo completo com PortfolioItem e PortfolioList fica da seguinte forma:

class PortfolioItem extends React.Component {
  render() {
    return (
      <article class="job">
        <h4 class="title">{this.props.nome}}</h4>
        <ul class="fetures">
          <li><a href="#" target="_blank" alt="site">{this.props.site}</a></li>
          <li>Empresa: {this.props.empresa}</li>
          <li>Tecnologias: {this.props.tecnologias}</li>
        </ul>
      </article>
    )
  }
}

class PortfolioList extends React.Component {
  render() {
    const jobsList = [],
          data = [
          {"nome": "job 1", "site": "http://fellyph.com.br/", "empresa": "Empresa 1", "tecnologias": ["HTML", "CSS", "JS"]},
          {"nome": "job 2", "site": "http://fellyph.com.br/", "empresa": "Empresa 2", "tecnologias": ["HTML", "CSS", "JS"]},
          {"nome": "job 3", "site": "http://fellyph.com.br/", "empresa": "Empresa 3", "tecnologias": ["HTML", "CSS", "JS"]},
          {"nome": "job 4", "site": "http://fellyph.com.br/", "empresa": "Empresa 4", "tecnologias": ["HTML", "CSS", "JS"]}];

    data.forEach( function(job) {
      jobsList.push(<PortfolioItem nome={job.nome} site={job.site} empresa={job.empresa} tecnologias={job.tecnologias} />);
    });

    return (
      <div className="jobs">
        {jobsList}
      </div>
    );
  }
}

ReactDOM.render(
  <PortfolioList />, document.getElementById('portfolio')
);

No código acima adicionei o JSON como uma constante do nosso componente o ideal que essas dados venha de alguma API. Na sequência leio o JSON e crio um array com componentes PortfolioItem e no render eu apenas passo o array que montamos {jobsList}. Por fim chamamos o ReactDOM.render passando o PortfolioList como o elemento que iremos adicionar o componente.

O nosso HTML fica da seguinte forma:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Pensando em React</title>
  </head>
  <body>
    <h3>Portfolio</h3>
    <div id="portfolio"></div>
    <script src="https://fb.me/react-15.1.0.js"></script>
    <script src="https://fb.me/react-dom-15.1.0.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
    <script type="text/babel" src="src/js/components.js"></script>
  </body>
</html>

Podemos organizar melhor o nosso componente PortfolioList, podemos adicionar funções para organizar o seu comportamento, como no código abaixo:

class PortfolioList extends React.Component {
  _getJobs () {
    const var jobsList = [
      {"nome": "job 1", "site": "http://fellyph.com.br/", "empresa": "Empresa 1", "tecnologias": ["HTML", "CSS", "JS"]},
      {"nome": "job 2", "site": "http://fellyph.com.br/", "empresa": "Empresa 2", "tecnologias": ["HTML", "CSS", "JS"]},
      {"nome": "job 3", "site": "http://fellyph.com.br/", "empresa": "Empresa 3", "tecnologias": ["HTML", "CSS", "JS"]},
      {"nome": "job 4", "site": "http://fellyph.com.br/", "empresa": "Empresa 4", "tecnologias": ["HTML", "CSS", "JS"]}
    ];

    return jobsList.map((job) => {
      return (<PortfolioItem nome={job.nome} site={job.site} empresa={job.empresa} tecnologias={job.tecnologias} />);
    })
  }

  render() {
    const jobs = this._getJobs();
    return (
      <h3>Portfolio</h3>
      <div className="jobs">
        {jobs}
      </div>
    )
  }
}

Na atualização do componente adicionamos uma função “_getJobs” responsável para carregar os trabalhos, separamos a lógica de ler os dados da lógica de renderizar os dados. Também usei alguns recursos novos do ECMAScript2015.

Podemos evoluir esse post, mas pretendo ir evoluindo estes exemplos em outros posts, por isso adicionei um repositório no git: https://github.com/fellyph/react-tutorial