项目作者: markostanimirovic

项目描述 :
Declarative and Zone-Less Angular Components With Ivy Features and NgRx
高级语言: TypeScript
项目地址: git://github.com/markostanimirovic/declarative-components.git
创建时间: 2020-10-08T01:14:22Z
项目社区:https://github.com/markostanimirovic/declarative-components

开源协议:MIT License

下载


Declarative and Zone-Less Angular Components With Ivy Features and NgRx

TLDR; What’s the goal?

To transform this:

  1. @Component({
  2. selector: 'app-movies',
  3. templateUrl: './movies.component.html',
  4. })
  5. export class MoviesComponent {
  6. movies$ = this.store.select(selectMovies);
  7. selectedMovie$ = this.store.select(selectSelectedMovie);
  8. constructor(private store: Store) {}
  9. onAddMovie(movie: string): void {
  10. this.store.dispatch(MoviesActions.addMovie({ movie }));
  11. }
  12. onUpdateSelectedMovie(selectedMovie: string): void {
  13. this.store.dispatch(MoviesActions.updateSelectedMovie({ selectedMovie }));
  14. }
  15. onRemoveSelectedMovie(): void {
  16. this.store.dispatch(MoviesActions.removeSelectedMovie());
  17. }
  18. }

into this:

  1. @Component({
  2. selector: 'app-movies',
  3. templateUrl: './movies.component.html',
  4. })
  5. @ComponentFeatures([
  6. withSelectors({
  7. movies: selectMovies,
  8. selectedMovie: selectSelectedMovie,
  9. }),
  10. withActions(MoviesActions),
  11. ])
  12. export class MoviesComponent {
  13. movies!: string[];
  14. selectedMovie!: string;
  15. actions!: typeof MoviesActions;
  16. }

Introduction

Let’s first recap the concepts that are important for this article.

What is Zone.js?

Zone.js a script that is executed before the Angular application is bootstrapped. It
monkey patches
asynchronous browser APIs (e.g. setTimeout, setInterval, addEventListener, Promise) by adding the code that will tell the Angular when
to run change detection mechanism. You can check that by opening the console in your Angular app and running the following code:

zone-js-monkey-patching

Angular wraps zone.js within the NgZone service. ApplicationRef injects it, listens to the onMicrotaskEmpty observable and invokes
tick method that will trigger the change detection mechanism.

  1. @Injectable()
  2. export class ApplicationRef {
  3. constructor(private _zone: NgZone) {
  4. this._zone.onMicrotaskEmpty.subscribe(() => {
  5. this._zone.run(() => this.tick());
  6. });
  7. }
  8. }

Zone.js tells Angular when to run the change detection, but it has a couple of downsides:

  • Not tree shakable (uncompressed size >100kB)
  • Slower application bootstrap speed
  • Unnecessary change detection triggering
  • Hard to debug
  • Cannot monkey patch native async/await

Trigger Change Detection Manually

If you exclude Zone.js from your Angular application, the change detection will not work.
To make it work again, you need to run change detection somehow. For that purpose, Angular has ɵmarkDirty function.
ɵmarkDirty accepts a component instance as an argument and when invoked, it will go up to the root component and schedule
change detection.

  1. import { Component, ɵmarkDirty } from '@angular/core';
  2. @Component({
  3. selector: 'app-counter',
  4. template: `
  5. <h1>Counter</h1>
  6. <div>
  7. <button (click)="onIncrement()">+</button>
  8. <span>{{ count }}</span>
  9. <button (click)="onDecrement()">-</button>
  10. </div>
  11. `,
  12. })
  13. export class CounterComponent {
  14. count = 0;
  15. onIncrement(): void {
  16. this.count++;
  17. ɵmarkDirty(this);
  18. }
  19. onDecrement(): void {
  20. this.count--;
  21. ɵmarkDirty(this);
  22. }
  23. }

And change detection works again! However, it’s not awesome to trigger it manually every time when the state of component is updated.
You will probably miss calling ɵmarkDirty somewhere.

Trigger Change Detection Automatically

Thankfully, there are few approaches how to trigger change detection automatically in zone-less environment:

  1. Push Pipe and RxLet Directive by Michael Hladky
    (see the prototype of push pipe here)
  2. Reactive Component by Mike Ryan

Third approach is via Ivy Features. Let’s take a closer look at them.

Ivy Features

UNDER_CONSTRUCTION