Это обсуждение перечисляет несколько стратегий https://github.com/angular/angular/issues/6674#issuecomment-174699245
вопрос имеет много последствий. В некоторых случаях наблюдаемые должны управляться вне рамок.
A. Вы можете сканировать все наблюдаемые, прежде чем самонастройки
B. Bootstrap отсканировать все наблюдаемые перед передачей объекта в компонент верхнего уровня.
C. Вы также можете изменить changeDetection в компоненте, чтобы либо запускать, когда входы меняются, либо вручную запускают их.
D. Если вы используете | async, то его следует использовать только на верхнем уровне, если вам не нравится использовать .subscribe, но вы действительно должны просто использовать .subscribe.
E. Если вы используете | async везде, то то, что вы действительно делаете, - это инвертирование контроля над визуализацией на наблюдаемые, что означает, что мы вернулись в Angular1 дней каскадных изменений, так что вам либо нужно делать C, D, B или A
ChangeDetectionStrategy похоже не работает в данный момент. Вы бы просто установили компонент как отдельный.
Мы также можем использовать крючок жизненного цикла ngOnInit для удаления компонента из дерева обнаружения изменений. Вам нужно будет запустить this.ref.detach(); где исх вводится через 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
Вы можете также не включать в zone.js и вручную контролировать все изменения. Вы также можете ввести NgZone для запуска операции вне зоны.js, чтобы он не указывал угловое значение для запуска шайб. Например,
// 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
}
}
Thanks Mark! Элвис сделал трюк! Но я пока не понимаю поток рендеринга. Шаблон визуализируется каждый раз, когда есть какие-либо изменения в свойствах компонента? –
@TonyAlexanderHild, при обнаружении углового изменения (который запускается после каждого события) по умолчанию все ваши привязки к просмотру/шаблону грязно проверены, то есть они проверяются на изменения. Когда данные возвращаются с сервера, это событие, поэтому выполняется проверка обнаружения изменений. 'model.Name' грязно проверено и обнаружено, что оно изменилось, поэтому Angular обновляет DOM. После того, как Angular возвращает управление браузеру, он видит изменения DOM и обновляет то, что мы видим на экране. –
Спасибо @MarkRajcok! Теперь ясно. –