Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Você ainda não sabe escrever JavaScript para ap...

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

Você ainda não sabe escrever JavaScript para aplicações Rails

Uma palestra com as principais tecnologias e técnicas utilizadas para escrever código JavaScript sano para diferentes tipos de aplicações. Uma viagem às antigas soluções Rails até as atuais e nem sempre suficientes jQuery UJS e Turbolinks. Aprenda sobre componentes auto-discoverable, comunicação através de eventos, modularização e gerência de dependências. Tudo isto sem deixar de fora alguns dos conceitos por trás dos principais frameworks MV* do mercado.

Avatar for Jean Carlo Emer

Jean Carlo Emer

August 29, 2014
Tweet

More Decks by Jean Carlo Emer

Other Decks in Programming

Transcript

  1. [...] é necessário ir ao passado para a compreensão de

    todos os questionamentos do tempo presente - Historiador Tiago Menta
  2. <%  form_remote_tag  :url  =>  '/'  do  -­‐%>      

       <div><%=  submit_tag  'Save'  %></div>   <%  end  -­‐%> index.erb
  3. <form action="/" method="post" onsubmit="
 new Ajax.Request('/', {asynchronous:true, 
 evalScripts:true, parameters:


    Form.serialize(this)}); return false;"> <input name="commit" type="submit" /> </form> index.html
  4. <%=  observe_field(:local_estado_id,            :update  =>  "local_cidade_id",

               :url  =>  cidades_options_for_select_path,            :with  =>  "estado_id"  %> index.erb
  5. <select  id="local_estado_id"                

       name="local[estado_id]"><!-­‐-­‐  -­‐-­‐></select>   ! <script  type="text/javascript">   //<![CDATA[      new  Form.Element.EventObserver('local_estado_id',         ! ! ! //]]>   </script> !@#$%^@!% index.html
  6. update_page  do  |page|      page.insert_html  :bottom,  'list',    

           "<li>#{@item.name}</li>"      page.visual_effect  :highlight,   'list'   end controller/action.rb
  7. new  Element.insert("list",            {  bottom:  "<li>Some

     item</li>"  });   new  Effect.Highlight("list"); response.js
  8. JavaScript não deve estar no markup Código back-end não deve

    depender de biblioteca front-end. ♥ ♥
  9. Rails 3.0 Fim das chamadas Ajax através de JavaScript inline

    e dos observers https://github.com/rails/prototype_legacy_helper
  10. <%=  link_to  "Other  Site",  "url",         data:

     {  confirm:  "Are  you  sure?"  }  %> index.erb
  11. Considere que o formulário também pode ser enviado sincronamente pelo

    usuário E se não executar o 
 JavaScript?
  12. <%=  link_to  "Destroy",  "url",  
          

                   method:  :delete  %> index.erb
  13. O usuário irá apenas ler a notícia, considere sempre utilizar

    formulários para este tipo de ação E se não executar o 
 JavaScript?
  14. $('#photo_<%=  params[:id]  %>').remove(); destroy.js.erb photo.html <a  href="photo/2"      

       data-­‐method="delete"          data-­‐remote="true">Destroy</a>  
  15. <%-­‐  if  @contact.errors.any?  %>      $('#contact-­‐modal').html('<%=   escape_javascript(render(partial:  'form'))

        )  %>');   <%-­‐  else  %>      $('#contact-­‐modal').html('<%=   !       !   $('#contact-­‐modal').append('<p  class="alert  
 alert-­‐success">Your  message  was  successfully  
 sent  </p>');      setTimeout("$('.close').click();",  2000);   <%-­‐  end  %> !@#$%^@!% create.js.erb
  16. class  Counter      constructor:  (@min  =  0,  @max  =

     10e9)  -­‐>          @current  =  @min      next:  -­‐>          @current  =  Math.min(@max,  @current  +  1)      isFirst:  -­‐>          @current  <=  @min   ! class  CounterPlus  extends  Counter      goToLast:  -­‐>          @current  =  @max counter.coffee
  17. function  Counter(min,  max)  {          this.min  =

     min  !=  null  ?  min  :  0;          this.max  =  max  !=  null  ?  max  :  10e9;          this.current  =  this.min;   }   ! Counter.prototype.next  =  function()  {          return  this.current  =  
       Math.min(this.max,  this.current  +  1)   }   ! Counter.prototype.isFirst  =  function()  {          return  this.current  <=  this.min   }   ! function  CounterPlus()  {   counter.js
  18. ! Counter.prototype.isFirst  =  function()  {          return

     this.current  <=  this.min   }   ! function  CounterPlus()  {          Counter.apply(this,  arguments)   }   ! function  InheritCounter()  {}   InheritCounter.prototype  =  Counter.prototype   ! CounterPlus.prototype  =  new  InheritCounter()   CounterPlus.prototype.constructor  =  CounterPlus   ! CounterPlus.prototype.goToLast  =  function()  {          return  this.current  =  this.max   }
  19. Não é por nada que o EcmaScript 6 usa o

    CoffeeScript como referência
  20. RUBYCONF
 
 CONHEÇA OS PALESTRANTES PROMETE TRAZER NOVIDADES E ASSUNTOS

    PERTINENTES DA ÁREA Requisição Ajax pela página apontada no link
  21. A barra de endereços é atualizada e as páginas visitadas

    são armazenadas (voltar à uma página é imediato)
  22. Assets devem ficar no <head> e precisam ser marcados para

    que modificações sejam monitoradas (e recarregada caso preciso)
  23. Suporte para widgets do Facebook, Twitter, Google+, Google Analytics, AdSense

    e alguns mais http://reed.github.io/turbolinks-compatibility
  24. A cada transição os events handlers e demais callbacks devem

    ser desativados para não interferir na performance
  25. Código JavaScript pode ser executado na troca de páginas Widgets

    e add-ons funcionam de acordo depois de ajustados Memory leaks podem ser evitados ♥ ♥ ♥
  26. O Turbolinks não permite que apenas porções da página sejam

    requisitadas (confira o jquery-pajax para isto)
  27. Turbolinks funciona bem 
 em websites simples (como o 


    desta conferência) e forma uma 
 boa dupla com UJS
  28. O JavaScript não possui sistema de módulos fazendo com que

    diferentes scripts compartilhem o mesmo escopo
  29. file1.js file2.js Sem a criação de um escopo, as variáveis

    ficam expostas var  myVar  =  "bla"; alert(myVar);
  30. (function  ()  {      var  data  =  {};  

       function  parser()  {            //  Code      }   })(); Immediately-Invoked Function Expression viabilizam a criação de escopos http://benalman.com/news/ 2010/11/immediately- invoked-function-expression
  31. App.modules.mediabox  =  (function  ()  {      var  data  =

     {};   !    return  {            data:  data,            parser:  //  ...      }   })(); Namespaces mediabox.js (namespace)
  32. Module('modules.mediabox',  
    function  (Mediabox)  {        

     Mediabox.data  =  {};        Mediabox.parser  =  //  ...      }   ); Biblioteca de módulos do Nando Vieira http://simplesideias.com.br/ escrevendo-javascript-modular mediabox.js (Module.js)
  33. define(      [          'jquery',  

             'util/counter'      ],      function  ($,  Counter)  {          //  ...                  return  {              Mediabox:  Mediabox,              //  ...          };      }
 ); mediabox.js (AMD) Módulos AMD que permitem indicação de dependências https://github.com/ jwhitley/requirejs-rails
  34. Declaração de dependências Path do arquivo como identificador do módulo

    Assíncrono por natureza e adotado
 por jQuery e outras bibliotecas ♥ ♥ ♥
  35. [...] it makes code easier to understand for others and

    yourself re-visting your own code - Chris Coyier
  36. ES6 Modules e CommonJS Modules não possuem suporte adequado 


    ao Asset Pipeline (alguém se habilita?)
  37. main.js //  Setup  product  page   if  ($('body').is('.page-­‐product'))  {  

       $("[data-­‐draggable]").draggable()      $("[data-­‐comments]").comments()   }   ! //  Setup  checkout  page   if  ($('body').is('.page-­‐checkout'))  {      $("[data-­‐draggable]").draggable()      $("[data-­‐datepicker]").datepicker()   }
  38. main.js //  Setup  product  page   if  ($('body').is('.page-­‐product'))  {  

       $("[data-­‐draggable]").draggable()      $("[data-­‐comments]").comments()   }   ! //  Setup  checkout  page   if  ($('body').is('.page-­‐checkout'))  {      $("[data-­‐draggable]").draggable()      $("[data-­‐datepicker]").datepicker()   }
  39. define(function  ()  {      function  Mediabox(container)  {    

         //  ...      }      return  Mediabox;   }); Chamada do construtor
 com o container mediabox.js
  40. Trabalhar com models que emitem eventos é trabalhoso e passível

    a erros (não entenda mal, Backbone.js) ♥
  41. <div  ng-­‐controller="Basket">      <select  ng-­‐model="quantity"  
      

                 ng-­‐init="quantity=1">          <option>1</option><option>10</option>      </select>      <div>Valor:  R$  {{price()}}</div>   </div> index.html function  Basket($scope)  {          $scope.price  =  function  ()  {                  return  $scope.quantity  *  50;                              };   } main.js
  42. <div  ng-­‐app="component">      <tabs>          <pane

     title="Date">              Date:  {{  '2012-­‐04-­‐01'  |  date:'fullDate'  }}          </pane>          <pane  title="Hello">              Hi!          </pane>      </tabs>   </div> Tags são mapeadas para templates e controllers
  43. What’s wrong with Angular.js https://medium.com/este-js-framework/whats- wrong-with-angular-js-97b0a787f903 What I would recommend

    instead of Angular.js? https://medium.com/este-js-framework/what-i- would-recommend-instead-of-angular- js-62b057d8a9e
  44. Estude sobre execução de código assíncrono com callbacks e promises

    https://speakerdeck.com/jcemer/controle-de- fluxo-com-execucao-assincrona 1.
  45. Aceite que o JavaScript do front-end da sua aplicação pode

    dar tanto ou mais trabalho que o back-end 2.