javascript - Angular2 zone.run() 与 ChangeDetectorRef.detectChanges()

标签 javascript angular angular2-changedetection

假设我的 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.detectChangesChangeDetectorRef.markforCheck 效率更高。

如果来自外部的调用例如导航到不同的路由,这可能会对许多组件产生影响,并且也不清楚整个路由更改何时完成,因为它可能导致异步调用(和回调被调用) . 在这种情况下,zone.run() 是更好的选择,因为直接和间接调用的代码(比如可观察对象和 promise 的回调)将在 Angular 的区域内运行,Angular 将识别它们并调用变化检测自动。

关于javascript - Angular2 zone.run() 与 ChangeDetectorRef.detectChanges(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42971865/

相关文章:

Angular Material : mat-select not selecting default

Angular9使用HttpClient通过表单数据将数据发布到API

Angular2 RC6 管道。我可以在与我的组件相同的 .ts 文件中声明管道吗?

angular - 即使列表引用发生变化,如何重用 ngFor 的元素?

javascript - foo 的三元简写?富: bar

javascript - 在 Webpack 项目中获取 "Uncaught TypeError: path.parse is not a function"

angular - 您可以在 Angular 2 组件中同时使用 OnChanges 和 DoCheck 吗?

Angular2 ngFor OnPush 变化检测与数组突变

javascript - 根据 Firefox 中的区域设置格式化 "YYYY-MM-DD"日期字符串

javascript - 如何将固定定位元素堆叠在静态定位元素前面?