Desbravando Angular 2+ e TypeScript

William Grasel

@willgmbr

Angular quem?

  • Framework MVC, MV* ou MVW
  • Criado em 2009 por Miško Hevery no Google
  • Lançado à público em outubro de 2010, quase ao mesmo tempo que o BackboneJS
  • EmberJS foi lançado em dezembro de 2011
  • ReactJS em março de 2013

Angular em números

Google Apps by Angular

https://www.madewithangular.com/#/categories/google

A web mudou como nunca

  • Web Components
  • Shadow Dom
  • ES6 / ES2015 +
  • Web Workers
  • Service Workers
  • Mobile Apps

Angular 2.0

2014 ~ 2016

TypeScript, WTF??

  • Projeto opensource criado pela Microsoft
  • Mais um transpiler de JS para ES6, 7 e Next
  • Focado em tipos, interfaces e ferramentas assíncronas
  • Onde todas as features são estritamente opcionais
  • Todo JavaScript válido deve ser um TS válido
  • Promete se manter fiel ao futuro do ES Next
  • Foco no ferramental e refactor de grandes apps

Ferramental, Refactor?

Você não precisa tipar seu código

Mas ainda assim pode se beneficiar da tipagem!

Google está sozinho?

Sou obrigado a usar TypeScript?

Arquitetura 2+

Componentes

  • Base da nova arquitetura do Angular 2+
  • São diretivas que tem uma interface com o usuário através de um template
  • Contem a lógica de interação com usuário
  • São criadas, atualizadas e destruidas pelo angular conforme o usuário interage com a aplicação
  • Contém métodos de rastreio para acompanhar seu ciclo de vida

Exemplo de Componentes


  @Component({
    selector: 'hero-detail',
    templateUrl: 'app/hero-detail.html'
  })
  class HeroDetailComponent {
    @Input() hero;
    @Output() update = new EventEmitter();

    constructor() {}

    ngOnInit() {}
    ngOnDestroy() {}
  }

Diretivas

  • São objetos de manipulação dinâmica de templates, sem template próprio e sem interação direta com o usuário
  • Vem em dois sabores distintos:
  • Estruturais: que alteram o layout adicionando, removendo ou substituindo porções do template, como *ngIf, *ngFor
  • Atributos: modificam a aparência ou o comportamento de um outro elemento, como o [(ngModel)]

Exemplo de Diretivas


  @Directive({
    selector: '[myUnless]'
  })
  class MyUnlessDirective {
    constructor(
      private templateRef: TemplateRef,
      private viewContainer: ViewContainerRef
    ) {}

    @Input()
    set myUnless(value) {
      if (value)
        this.viewContainer.createEmbeddedView(this.templateRef);
      else this.viewContainer.clear();
    }
  }

Services

  • É uma categoria ampla como valores, funções, objetos que sejam necessárias para sua aplicação
  • Quase tudo pode ser um serviço, porém cada um deve ter um objetivo e significado único e bem definido
  • Essas são apenas sugestões
  • Angular em si não toma partido sobre como seus services devem ser construídos ou se comportarem

Exemplo de Serviços


  @Injectable()
  class UserService {
    constructor(
      private http: HttpClient,
    ) {}

    getAll() {
      return this.http.get('api/users');
    }
  }

Pipes / Filtros

  • Filtros agora são chamados de Pipes e foram reformulados
  • Pois eram grande causadores de perda de performance
  • Alguns como filter e orderBy não existem mais
  • Pipes são puros por padrão, executando funções puras
  • Somente são executados se a referência mudar
  • Se um filtro puro receber um mesmo objeto duas vezes em ciclos diferentes, o pipe não será executado novamente, mesmo que seus atributos tenham mudado

Exemplo de Pipes


  @Pipe({
    name: 'flyingHeroes'
  })
  class FlyingHeroesPipe {
    transform(allHeroes) {
      return allHeroes
        .filter(hero => hero.canFly);
    }
  }

  <div *ngFor="let hero of (heroes | flyingHeroes)">
    {{hero.name}}
  </div>

Data Binding


  <div>{{model.name}}</div>

  <div>{{model.name}}</div>

  <model-detail [model]="model"></model-detail>

  <div>{{model.name}}</div>

  <model-detail [model]="model"></model-detail>

  <div (click)="selectItem(model)"></div>

  <div>{{model.name}}</div>

  <model-detail [model]="model"></model-detail>

  <div (click)="selectItem(model)"></div>

  <input [(ngModel)]="model.name">

Two way data binding como sugar sintaxe


  <input
    [value]="model.name"
    (input)="model.name = $event.target.value">

  <input
    [ngModel]="model.name"
    (ngModelChange)="model.name = $event">

  <input [(ngModel)]="model.name">

  [(x)]="e" <==> [x]="e" (xChange)="e=$event"

Detecção de mudanças

  • AngularJS 1.x faz custosos ciclos de dirty checking por toda aplicação a cada mudança nos objetos em seu escopo
  • Angular 2+ cria uma estrutura de grafo em árvore com os componentes, varrendo de forma unidirecional, da raíz para as folhas, propagando as mudanças para evitar novos ciclos
  • Estratégia padrão ainda varre a árvore toda

Grafo em Árvore?

Lembram?

Dados Imutável como a cereja do bolo

  • Angular 2+ sabe tirar proveito de dados imutáveis
  • Podemos mudar a estratégia de atualização dos componentes, ou da aplicação como um todo, para uma mais performática
  • Imutabilidade requer novos paradigmas de programação para se tornar prático e fluente em nosso dia a dia
  • Programação Funcional, Reativa e Streams ao resgate

Streams são a fundação do Angular

  • Streams são fluxos de dados assíncronos
  • Parecidos com promises mas, muito mais poderosos
  • Podem ser mergeados e transformados declarativamente
  • Http e outros módulos que retornavam promises agora retornam streams, retrocompatíveis com promises
  • Reactive Extensions (RxJS) é o novo $q

  // TypeScript
  import { Component, ChangeDetectionStrategy } from '@angular/core';
  import { Observable } from 'rxjs/Rx';

  // TypeScript
  import { Component, ChangeDetectionStrategy } from '@angular/core';
  import { Observable } from 'rxjs/Rx';

  @Component({
    selector: 'hero-message',
    changeDetection: ChangeDetectionStrategy.OnPush,
    template: '<p>Hey: {{ messages | async }}</p>',
  })

  // TypeScript
  import { Component, ChangeDetectionStrategy } from '@angular/core';
  import { Observable } from 'rxjs/Rx';

  @Component({
    selector: 'hero-message',
    changeDetection: ChangeDetectionStrategy.OnPush,
    template: '<p>Hey: {{ messages | async }}</p>',
  })
  export class HeroAsyncMessageComponent {
    private messageList = [
      'You are my hero!',
      'You are the best hero!',
      'Will you be my hero?'
    ];

  // TypeScript
  import { Component, ChangeDetectionStrategy } from '@angular/core';
  import { Observable } from 'rxjs/Rx';

  @Component({
    selector: 'hero-message',
    changeDetection: ChangeDetectionStrategy.OnPush,
    template: '<p>Hey: {{ messages | async }}</p>',
  })
  export class HeroAsyncMessageComponent {
    private messageList = [
      'You are my hero!',
      'You are the best hero!',
      'Will you be my hero?'
    ];
    constructor() {
      this.messages = Observable.interval(500)
        .map(i => this.messageList[i])
        .take(this.messageList.length);
    }
  }

Extensões Reativas Oficiais

  • Extensões oficiais de alta qualidade para tirar o máximo de proveito dos paradigmas funcionais e reativos
  • Vários módulos já disponíveis:

ngrx/store

ngrx/effects

Muito além da performance

Angular CLI


  > npm install -g angular-cli

  > ng --help

  > npm install -g angular-cli

  > ng --help

  > ng new myProjectName

  > npm install -g angular-cli

  > ng --help

  > ng new myProjectName

  > ng serve

  > npm install -g angular-cli

  > ng --help

  > ng new myProjectName

  > ng serve

  > ng generate route|component|etc myName

  > npm install -g angular-cli

  > ng --help

  > ng new myProjectName

  > ng serve

  > ng generate route|component|etc myName

  > ng build

  > npm install -g angular-cli

  > ng --help

  > ng new myProjectName

  > ng serve

  > ng generate route|component|etc myName

  > ng build

  > ng test

  > ng e2e

Migrando para Angular 2+

  • Migração pode ser feita aos poucos
  • As duas versões podem ser executadas em conjunto
  • É possível utilizar componentes, diretivas, services e filtros do Angular 2+ em uma aplicação AngularJS 1.x e vice versa

Mas como?


  import { UpgradeAdapter } from '@angular/upgrade';

  const adapter = new UpgradeAdapter();
  const app = angular.module('myApp', []);

  adapter.bootstrap(document.body, ['myApp']);


  // Usando Angular2 Componentes numa app Angular1

  app.directive('productDetail',
    adapter.downgradeNg2Component(ProductDetail));


  // Usando Angular1 Componentes numa app Angular2

  const HeroDetail = adapter
    .upgradeNg1Component('heroDetail');

Suporte IE9+

Vamos começar hoje mesmo? \o/

Referências

Perguntas?

Obrigado! =)

@willgmbr

Desbravando Angular 2+ e TypeScript

By William Grasel

Desbravando Angular 2+ e TypeScript

O que esperar da reformulação de um dos frameworks de SPA mais utilizados no mundo? A competitividade aumentou muito durante os anos de sua reescrita, mas o Angular ainda continua como um dos principais players de mercado. Vamos descobrir o que mudou desde sua última versão, quais influências trás de seus concorrentes e como pretende alavancar o futuro do desenvolvimento Web.

  • 5,756