Questa discussione elenca alcune strategie https://github.com/angular/angular/issues/6674#issuecomment-174699245
La questione ha molte implicazioni. In alcuni casi, gli osservabili dovrebbero essere gestiti al di fuori del quadro.
A. È possibile eseguire la scansione di tutte le osservabili prima di bootstrap
B. Bootstrap quindi la scansione di tutti osservabili prima di passare l'oggetto al componente di livello superiore.
C. È inoltre possibile modificare la modifica del rilevamento all'interno del componente per attivare quando gli ingressi cambiano o attivare manualmente il rilevatore di modifiche.
D. Se si utilizza | async, dovrebbe essere utilizzato solo al livello superiore se non si ha voglia di usare .subscribe ma si dovrebbe semplicemente usare .subscribe.
E. Se si utilizza Async dappertutto, ciò che si sta facendo in realtà è invertendo il controllo del rendering verso l'osservabile, il che significa che siamo di nuovo nei tempi Angular1 dei cambiamenti a cascata in modo che sia necessario fare C, D, B, o A
ChangeDetectionStrategy non sembra funzionare al momento. È semplice impostare il componente come Staccato.
Possiamo inoltre utilizzare il hook del ciclo di vita ngOnInit per rimuovere il componente dall'albero di rilevamento delle modifiche. Dovresti eseguire this.ref.detach(); dove ref viene iniettato attraverso ChangeDetectorRef
ngOnInit() {
this.ref.detach();
}
makeYourChanges() {
this.ref.reattach(); // attach back to change detector tree
this.data.value = Math.random() + ''; // make changes
this.ref.detectChanges(); // check as dirty
this.ref.detach(); // remove from tree
// zone.js triggers changes
}
ChangeDetectorRef
È possibile anche includere non zone.js e controllare manualmente tutte le modifiche. È inoltre possibile iniettare NgZone per eseguire un'operazione al di fuori di zone.js in modo che non sia detto angolare per attivare i canali. Ad esempio,
// this example might need a refactor to work with rxjs 5
export class Timeflies {
pos = 'absolute';
color = 'red';
letters: LetterConfig[];
constructor(
private service: Message,
private el: ElementRef,
private zone: NgZone) {
}
ngOnInit() {
// initial mapping (before mouse moves)
this.letters = this.service.message.map(
(val, idx) => ({
text: val,
top: 100,
left: (idx * 20 + 50),
index: idx
})
);
this.zone.runOutsideAngular(() => {
Observable
.fromEvent(this.el.nativeElement, 'mousemove')
.map((e: MouseEvent) => {
//var offset = getOffset(this.el);
// subtract offset of the element
var o = this.el.nativeElement.getBoundingClientRect();
return {
offsetX: e.clientX - o.left,
offsetY: e.clientY - o.top
};
})
.flatMap(delta => {
return Observable
.fromArray(this.letters
.map((val, index) => ({
letter: val.text,
delta,
index
})));
})
.flatMap(letterConfig => {
return Observable
.timer((letterConfig.index + 1) * 100)
.map(() => ({
text: letterConfig.letter,
top: letterConfig.delta.offsetY,
left: letterConfig.delta.offsetX + letterConfig.index * 20 + 20,
index: letterConfig.index
}));
})
.subscribe(letterConfig => {
// to render the letters, put them back into app zone
this.zone.run(() => this.letters[letterConfig.index] = letterConfig);
});
});//zone
}
}
Grazie Mark! L'Elvis ha fatto il trucco! Ma non capisco ancora il flusso di rendering. Il modello viene sottoposto a rendering ogni volta che vengono apportate modifiche alle proprietà del componente? –
@TonyAlexanderHild, durante il rilevamento delle modifiche angolari (che viene eseguito dopo ogni evento), per impostazione predefinita, tutte le associazioni di visualizzazione/modello sono sporche, il che significa che vengono controllate le modifiche. Quando i dati vengono restituiti dal server, si tratta di un evento, quindi viene eseguito il rilevamento delle modifiche. 'model.Name' è sporco controllato e trovato modificato, quindi Angular aggiorna il DOM. Dopo che Angular restituisce il controllo al browser, vede il DOM cambiare e aggiorna ciò che vediamo sullo schermo. –
Grazie @MarkRajcok! Adesso è chiaro. –