AngularJS Style Guide

9eabf0151e0be8b4b91a156e624e28d4?s=47 willian
September 26, 2015

AngularJS Style Guide

9eabf0151e0be8b4b91a156e624e28d4?s=128

willian

September 26, 2015
Tweet

Transcript

  1. @willian AngularJS Style Guide Melhorando a escalabilidade, legibilidade e pensando

    no futuro
  2. @willian AngularJS Style Guide Melhorando a escalabilidade, legibilidade e pensando

    no futuro
  3. @willian PRIORIDADE NA LEGIBILIDADE

  4. @willian CADA CÓDIGO TEM SEU PRÓPRIO MÓDULO

  5. @willian SEJA EXPLÍCITO, NÃO IMPLÍCITO

  6. @willian PENSE NO FUTURO ES6 e Web Components (Angular 2.0)

  7. @willian WILLIAN FERNANDES

  8. @willian

  9. @willian REFERÊNCIA https://github.com/gocardless/angularjs-style-guide

  10. @willian DEPENDÊNCIAS GERAIS

  11. @willian SYSTEMJS Um carregador de módulos ES6 que nos permite

    importar assets em ambiente de desenvolvimento convertendo ES6 para ES5.
  12. @willian 'use strict'; import angular from 'angular'; import {mainModule} from

    './main'; angular.element(document).ready(function() { angular.bootstrap(document.querySelector('[data-main-app]'), [ mainModule.name ], { strictDi: true }); });
  13. @willian BABEL ES6 => ES5

  14. @willian JSPM Carrega qualquer formato de módulo (ES6, AMD, CommonJS)

    diretamente de repositórios Github, npm e mais.
  15. @willian LODASH Funções úteis para turbinar seu código JavaScript.

  16. @willian var conference = { name: 'Front in Vale' };

    _.assign(conference, { 'date': '2015-09-26' }); // → { 'name': 'Front in Vale', 'date': '2015-09-26' }
  17. @willian UI-ROUTER Permite-nos trabalhar com states ao invés de rotas

    URL e nested views.
  18. @willian ESTRUTURA DE DIRETÓRIOS

  19. @willian . ├── app │ ├── bootstrap.js │ ├── components

    │ │ ├── loading-view │ │ │ ├── loading-view_controller.js │ │ │ ├── loading-view_directive.js │ │ │ └── loading-view_template.html │ │ └── site-header │ │ ├── site-header_controller.js │ │ ├── site-header_directive.js │ │ └── site-header_template.html │ ├── main.js │ ├── routes │ │ └── todo │ │ ├── todo_controller.js │ │ ├── todo_route.js │ │ └── todo_template.html │ └── services │ ├── api │ │ └── api.js │ └── todo │ ├── todo.js │ └── todo.spec.js ├── assets │ ├── fonts │ ├── images │ └── stylesheets │ ├── app.scss │ ├── base │ │ ├── _functions.scss │ │ ├── _mixins.scss │ │ └── _variables.scss │ ├── core │ │ ├── _basic.scss │ │ └── _vendor.scss │ ├── layout │ │ └── _header.scss │ └── ui │ └── _loading_bar.scss ├── config │ └── config.json └── index.html
  20. @willian TESTS (UNIT/E2E) Cada arquivo de teste fica dentro do

    diretório do código principal.
  21. @willian COMPONENTS Cada componente contém todo o HTML, CSS, JavaScript

    e outras dependências para ser renderizado.
  22. @willian ROUTES Responsável por configurar URLs e templates específicos para

    cada rota, podendo ou não conter seu próprio controller.
  23. @willian SERVICES Lógica de negócio.

  24. @willian REGRAS GERAIS

  25. @willian ROTAS Use resolvers para injetar dados.

  26. @willian 'use strict'; import angular from 'angular'; import 'angular-ui-router'; import

    {todoControllerModule} from './todo_controller'; import template from './todo_template.html!text'; export let todoRouteModule = angular.module('todoRouteModule', [ 'ui.router', todoControllerModule.name ]).config([ '$stateProvider', function TodoRoute($stateProvider) { $stateProvider.state('todo', { url: '/', template: template, controller: 'TodoController', controllerAs: 'ctrl', resolve: { tasks: [ 'Todo', function tasksResolver(Todo) { return Todo.get(); } ] } }); } ]);
  27. @willian DIRECTIVES Sempre use nomes compostos com hífen para separar

    palavras
  28. @willian <html> <body> <site-header></site-header> <loading-view></loading-view> </body> </html>

  29. @willian DIRECTIVES Sempre use tipo element quando precisar adicionar conteúdo.

  30. @willian <html> <body> <todo-list> <todo-tasks></todo-tasks> </todo-list> </body> </html>

  31. @willian DIRECTIVES Sempre use tipo attribute quando precisar adicionar um

    comportamento.
  32. @willian <html> <body> <input type="text" date-mask="99/99/9999"> </body> </html> Dispara um

    evento enquanto o usuário digita.
  33. @willian DIRECTIVES Use escopos isolados em element directives.

  34. @willian 'use strict'; import angular from 'angular'; import {siteHeaderControllerModule} from

    './site-header_controller'; import template from './site-header_template.html!text'; export var siteHeaderComponentModule = angular.module('siteHeaderComponentModule', [ siteHeaderControllerModule.name ]).directive('siteHeader', [ function siteHeader() { return { restrict: 'E', template: template, controller: 'SiteHeaderController', controllerAs: 'ctrl', bindToController: true, scope: { currentUser: '=currentUser', authenticated: '=authenticated' } }; } ]);
  35. @willian DIRECTIVES Sempre use bindToController quando usar escopos isolados.

  36. @willian 'use strict'; import angular from 'angular'; import {siteHeaderControllerModule} from

    './site-header_controller'; import template from './site-header_template.html!text'; export var siteHeaderComponentModule = angular.module('siteHeaderComponentModule', [ siteHeaderControllerModule.name ]).directive('siteHeader', [ function siteHeader() { return { restrict: 'E', template: template, controller: 'SiteHeaderController', controllerAs: 'ctrl', bindToController: true, scope: { currentUser: '=currentUser', authenticated: '=authenticated' } }; } ]);
  37. @willian CONTROLLERS Sempre use controllerAs.

  38. @willian 'use strict'; import angular from 'angular'; import {siteHeaderControllerModule} from

    './site-header_controller'; import template from './site-header_template.html!text'; export var siteHeaderComponentModule = angular.module('siteHeaderComponentModule', [ siteHeaderControllerModule.name ]).directive('siteHeader', [ function siteHeader() { return { restrict: 'E', template: template, controller: 'SiteHeaderController', controllerAs: 'ctrl', bindToController: true, scope: { currentUser: '=currentUser', authenticated: '=authenticated' } }; } ]);
  39. @willian CONTROLLERS Injete dados quando estiverem prontos ao invés de

    carregá-los.
  40. @willian 'use strict'; import angular from 'angular'; import 'angular-ui-router'; import

    {todoControllerModule} from './todo_controller'; import template from './todo_template.html!text'; export let todoRouteModule = angular.module('todoRouteModule', [ 'ui.router', todoControllerModule.name ]).config([ '$stateProvider', function TodoRoute($stateProvider) { $stateProvider.state('todo', { url: '/', template: template, controller: 'TodoController', controllerAs: 'ctrl', resolve: { tasks: [ 'Todo', function tasksResolver(Todo) { return Todo.get(); } ] } }); } ]);
  41. @willian 'use strict'; import angular from 'angular'; import _ from

    'lodash'; export let todoControllerModule = angular.module('todoControllerModule', [ ]).controller('TodoController', [ 'tasks', function TodoController(tasks) { let ctrl = this; _.assign(ctrl, { tasks: tasks; }); } ]);
  42. @willian CONTROLLERS Estenda o objeto controller para adicionar propriedades que

    serão utilizadas no template.
  43. @willian 'use strict'; import angular from 'angular'; import _ from

    'lodash'; export let todoControllerModule = angular.module('todoControllerModule', [ ]).controller('TodoController', [ 'tasks', function TodoController(tasks) { let ctrl = this; _.assign(ctrl, { tasks: tasks; }); } ]);
  44. @willian CONTROLLERS Se for adicionar lógica, que seja somente lógica

    de apresentação não lógica de negócio.
  45. @willian 'use strict'; import angular from 'angular'; import _ from

    'lodash'; export let todoControllerModule = angular.module('todoControllerModule', [ ]).controller('TodoController', [ 'Todo', 'tasks', function TodoController(Todo, tasks) { let ctrl = this; function addTask(taskName) { Todo.add({ name: taskName }); tasks = Todo.get(); } _.assign(ctrl, { addTask: addTask, tasks: tasks; }); } ]);
  46. @willian SERVICES E FACTORIES Sempre trate services como classes e

    nunca exporte services como uma única função.
  47. @willian 'use strict'; import angular from 'angular'; export var todoModule

    = angular.module('todoModule', []).factory('Todo', [ function Todo() { var tasks = []; function validate(task) { return (task.name !=== null && task.name !=== ''); } function get() { return tasks; } function add(task) { if (validate(task)) { tasks.push(task); } else { alert('Invalid data.'); } } return { get: get, add: add }; } ]);
  48. @willian MÓDULOS Sempre use lowerCamelCase para os nomes de módulos.

  49. @willian 'use strict'; import angular from 'angular'; export var todoModule

    = angular.module('todoModule', []).factory('Todo', [ function Todo() { ... } ]);
  50. @willian MÓDULOS Crie um módulo por arquivo.

  51. @willian 'use strict'; import angular from 'angular'; export var todoModule

    = angular.module('todoModule', []).factory('Todo', [ function Todo() { ... } ]);
  52. @willian 'use strict'; import angular from 'angular'; angular.module('app', []).factory('Todo', [

    function Todo() { ... } ]); X
  53. @willian USE MÓDULOS ES6 E também a propriedade name do

    módulos do Angular.
  54. @willian 'use strict'; import angular from 'angular'; import {siteHeaderControllerModule} from

    './site-header_controller'; import template from './site-header_template.html!text'; export var siteHeaderComponentModule = angular.module('siteHeaderComponentModule', [ siteHeaderControllerModule.name ]).directive('siteHeader', [ function siteHeader() { return { restrict: 'E', template: template, controller: 'SiteHeaderController', controllerAs: 'ctrl', bindToController: true, scope: { currentUser: '=currentUser', authenticated: '=authenticated' } }; } ]);
  55. @willian TEMPLATES Use sintaxe one-time binding quando possível.

  56. @willian <html> <body> <h1>{{::ctrl.systemName}}</h1> </body> </html> Evita watchers desnecessários

  57. @willian TEMPLATES Não use ngInit. Use controles.

  58. @willian TEMPLATES Não use ngController. Use directives.

  59. @willian <div ng-controller="Controller"> X

  60. @willian PATTERNS

  61. @willian ABSTRAÇÕES DO ANGULAR

  62. @willian • $timeout ao invés de setTimeout • $interval ao

    invés de setInterval • $window ao invés de window • $document ao invés de document • $http ao invés de $.ajax • $q (promises) ao invés de callbacks
  63. @willian SINTAXE DE INJEÇÃO DE DEPENDÊNCIAS

  64. @willian 'use strict'; import angular from 'angular'; import _ from

    'lodash'; export let todoControllerModule = angular.module('todoControllerModule', [ ]).controller('TodoController', [ 'tasks', function TodoController(tasks) { let ctrl = this; _.assign(ctrl, { tasks: tasks; }); } ]);
  65. @willian 'use strict'; import angular from 'angular'; import {mainModule} from

    './main'; angular.element(document).ready(function() { angular.bootstrap(document.querySelector('[data-main-app]'), [ mainModule.name ], { strictDi: true }); }); Lança um erro se a sintaxe para injetar dependências (array sintax) ou $inject não forem utilizados
  66. @willian ANTI-PATTERNS

  67. @willian NÃO USE $ PARA NOMES DE PROPRIEDADES

  68. @willian ctrl.$isActive = true X

  69. @willian NÃO USE GLOBAIS Resolva todas as dependências usando Dependency

    Injection.
  70. @willian 'use strict'; import angular from 'angular'; import _ from

    'lodash'; export let todoControllerModule = angular.module('todoControllerModule', [ ]).controller('TodoController', [ 'Todo', 'tasks', function TodoController(Todo, tasks) { let ctrl = this; function addTask(taskName) { Todo.add({ name: taskName }); tasks = Todo.get(); } _.assign(ctrl, { addTask: addTask, tasks: tasks; }); } ]);
  71. @willian OBRIGADO

  72. @willian REFERÊNCIA https://github.com/gocardless/angularjs-style-guide