假设我的 service.ts 中有一个 function noificationHandler()
,它在 angular 的上下文之外。
noificationHandler()
由第三方调用,noificationHandler()
基本上使用一个数组并将该数组发送给已订阅其服务的组件。
service.ts
public mySubject: Subject<any> = new Subject();
public myObservable = this.mySubject.asObservable();
constructor() {
this.registry.subscribe("notification.msg",this.noificationHandler.bind(this));
}
noificationHandler(data) {
this.publishUpdate(data)
}
publishUpdate(data) {
this.mySubject.next(data);
}
component.ts
constructor(private service: myService) {
this.service.myObservable.subscribe(list => {
this.list = list;
});
}
^^^ 此时模板没有用新数据更新
由于 "notification.msg"
在 angular 的区域之外,angular
调用此事件("notification.msg")
时,不会运行 s 更改检测。
现在有两种调用变化检测的方法。
1) 通过将 noificationHandler()
包裹在 angular 的 zone.run() 中
this.registry.subscribe("a2mevent.notification.msg", this.ngZone.run(() => this.noificationHandler.bind(this)));
2) 通过单独要求组件检测变化
constructor(private service: myService, private ref: ChangeDetectorRef) {
this.service.myObservable.subscribe(list => {
this.list = list;
this.ref.detectChanges(); // <==== manually invoking change detection
});
}
这两个选项都有效! 而我的组件结构如下
A --> root component
B
C
D // my component is here (4 levels of nesting)
问题 -
1) detectChanges() 会只检测其自身组件的变化,还是也会对子组件运行变化检测?
2) zone.run() 是否会触发从根到叶的所有组件的变化检测?
在 zone.run() 和 detectChanges() 中,我很好奇哪个在性能方面更好?
最佳答案
ApplicationRef.tick
(与 setTimeout()
相同)和 zone.run()
导致对整个应用程序进行更改检测。在 Angular 中或由 Angular 添加的事件监听器(使用 View 绑定(bind)或 @HostBinding()
会导致对整个应用程序的更改检测。
ChangeDetectorRef.detectChanges
为特定组件(及其后代,如果适用,例如由于输入绑定(bind))运行变更检测
如果在 Angular 区域之外运行的某些代码调用 Angular 代码并更改状态,则需要显式调用更改检测,因为 Angular 无法知道状态已更改。
如果状态更改是组件本地的(例如组件字段),ChangeDetectorRef.detectChanges
或 ChangeDetectorRef.markforCheck
效率更高。
如果来自外部的调用例如导航到不同的路由,这可能会对许多组件产生影响,并且也不清楚整个路由更改何时完成,因为它可能导致异步调用(和回调被调用) .
在这种情况下,zone.run()
是更好的选择,因为直接和间接调用的代码(比如可观察对象和 promise 的回调)将在 Angular 的区域内运行,Angular 将识别它们并调用变化检测自动。
关于javascript - Angular2 zone.run() 与 ChangeDetectorRef.detectChanges(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42971865/