Ich habe angefangen, Angular2 zu erkunden (ich komme mit Angular1 und ein bisschen React-Hintergrund) und bin mit einem Problem festgefahren.

Ich möchte bestimmte Tastenanschläge an Aktionen in meiner Komponente binden, daher habe ich beschlossen, den Angular2-Lebenszyklus zum Binden / Aufheben der Bindung von Aktionen zu verwenden.

Wenn ich jedoch etwas aus einem Mausefallen heraus mache, funktioniert es, aber es wird nicht gerendert und eine Änderung wird erst sichtbar, wenn ein Digest-Zyklus ausgeführt wird.

Muss ich etwas explizit ausführen, um eine Ansicht zu aktualisieren?

Könnte mir jemand helfen, herauszufinden, was los ist? Jede Hilfe wäre sehr dankbar.


import {Component} from 'angular2/core';
const Mousetrap = require('mousetrap');

@Component({
  template: `<div>
    Video template: Mode {{ mode }}
    <input type="number" [(ngModel)]="mode"/>
  </div>`
})
export class Video {

  public mode: number;

  constructor() {
    this.mode = 0;
  }

  ngOnInit() {

    console.log('hello Video component');
    Mousetrap.bind('d', () => console.log('this.mode=', this.mode));
    Mousetrap.bind('i', () => this.incrementMode()); // doesn't work

    this.incrementMode(); // works
    this.incrementMode(); // works
    setTimeout(() => this.incrementMode(), 4000); // works

  }

  incrementMode() {
    console.log('incMode', this.mode++);
  };

  ngOnDestroy() {
    console.log('bye bye Video component');
    Mousetrap.unbind(['d', 'i']);
  }

}
19
Jan Vorcak 4 Jän. 2016 im 17:01

2 Antworten

Beste Antwort

Obwohl die Antwort von @ Günter absolut richtig ist, möchte ich eine andere Lösung vorschlagen.

Das Problem mit der Mousetrap - Bibliothek besteht darin, dass ihre Instanz außerhalb der eckigen Zone (siehe hier) . Um jedoch nach jedem asynchronen Ereignis eine Änderungserkennung auszulösen, sollte die Instanz innerhalb der eckigen Zone . Sie haben zwei Möglichkeiten, um dies zu erreichen:

  1. Verwenden Sie die Abhängigkeitsinjektion:
bootstrap(App, [provide(Mousetrap, { useFactory: () => new Mousetrap() }) ]);

// ...

@Component({
  selector: 'my-app', 
  // ...
})
export class App {
  constructor(@Inject(Mousetrap) mousetrap) {
    this.mousetrap = mousetrap;
    // ...
  }
  //...
}
  1. Erstellen Sie einfach eine Instanz von Mousetrap im Konstruktor:
@Component({
  selector: 'my-app', 
  // ...
})
export class App {
  constructor() {
    this.mousetrap = new Mousetrap();
    // ...
  }
  //...
}

In beiden Fällen haben Sie die Möglichkeit, die Mausefalleninstanz folgendermaßen zu verwenden:

ngOnInit() {
  this.mousetrap.bind('i', () => this.incrementMode()); // It works now!!!
  // ...
}

Jetzt müssen Sie nicht mehr ngZone.run() in jedem bind Aufruf verwenden. Im Falle einer Abhängigkeitsinjektion können Sie diese mousetrap -Instanz auch in jeder Komponente / jedem Dienst Ihrer Anwendung verwenden (nicht nur in der App -Komponente).

Siehe diesen Plunk. Ich benutze dort die Abhängigkeitsinjektion.

20
alexpods 4 Jän. 2016 im 15:22

Wenn MouseTrap etwas außerhalb von Angular ist, müssen Sie möglicherweise NgZone injizieren und Ihren Code wie folgt ausführen

  Mousetrap.bind('i', () => this.ngZone.run(() => this.incrementMode()));
9
Günter Zöchbauer 4 Jän. 2016 im 14:14