Angular 2

The pains of Angular 1

Characteristics

  • Declarative UIs
  • Imperative business logic
  • Bi-directional binding
  • Dependency Injection
  • Testable apps
  • Avoid DOM manipulation*

Issues

  • Global change detection
  • $scope and prototypal inheritance
  • String-based DI
  • Difficult to debug
  • No server-side rendering capable
  • Complex APIs and a lot of proprietary syntax

Angular 2

Enter the component world

Component driven architecture

Every angular 2 app is a reactive component tree. This means that every node (component) is capable of check for its own changes and decide wether to update or not.

 

This gives the developer an unprecedented level of control over change detection.

What triggers a change?

  • Events
  • Timers
  • Requests

Async change detection

Entering Zone.js

Zones can perform an operation - such as starting or stopping a timer, or saving a stack trace - each time that code enters or exits a zone. 

 

Zone.js hooks

  • onZoneCreated 
  • beforeTask
  • afterTask
  • onError

Zone.js also patches

  • Zone.setInterval()
  • Zone.alert()
  • Zone.prompt()
  • Zone.requestAnimationFrame()
  • Zone.addEventListener()
  • Zone.removeEventListener()
function main() {
  foo();
  setTimeout(doSomething, 2000);
  bar();
  baz();
}

var myZoneSpec = {
  beforeTask: function () {
    console.log('Before task');
  },
  afterTask: function () {
    console.log('After task');
  }
};

var myZone = zone.fork(myZoneSpec);
myZone.run(main);

// Logs:
// Before task
// After task
// Before task
// Async task
// After task

Angular creates change detector classes at runtime for each component.

Smarter CD

w/ Observables and Immutability

Immutability

@Component({
  template: `
    <h2>{{vData.name}}</h2>
    <span>{{vData.email}}</span>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
class VCardCmp {
  @Input() vData;
}

Observables

@Component({
  template: '{{counter}}',
  changeDetection: ChangeDetectionStrategy.OnPush
})
class CartBadgeCmp {

  @Input() addItemStream:Observable<any>;
  counter = 0;
    
  constructor(private cd: ChangeDetectorRef) {}

  ngOnInit() {
    this.addItemStream.subscribe(() => {
      this.counter++; // application state changed
      this.cd.markForCheck(); // marks path
    })
  }
}

Ideally, a component should be able to process inputs and produce an output in isolation.

 

It should have well defined boundaries.

Component

This introduces two basic issues

  • How do I share common functionality?
  • How do I provide my components with the context they require?

We need

  • Composable blocks that we can use to build UIs
  • A clear separation between business logic and these blocks.

Presentational

Components

  • Only concerned with how things look
  • May contain both presentational and container components
  • No dependencies on the rest of the app
  • They have their own css
  • Usually they don´t contain their own state, they just receive it from the container components.

Container Components

  • Only concerned with how things work
  • May contain both presentational and container components but usually no markup of their own.
  • They provide data and behavior to the presentational components.
  • They´re usually stateful and serve as data sources.
  • They contain business logic.

Unidirectional data flow

State

Actions

UI

BL

Rx, Store, Router, Hooks

  • State: app state and notifies about changes.
  • Container component: provides context as it bridges business logic with views.
  • Presentational component: reusable block that composes UI with inputs and outputs.
  • Actions: changes the state and executes side effects.

Additional features

  • Universal applications
  • Smarter change detection
  • Smarter tooling (when using TypeScript)
  • Performance gains.

Show me the code!

Made with Slides.com