【问题标题】:Angular2 zone.run() vs ChangeDetectorRef.detectChanges()Angular2 zone.run() 与 ChangeDetectorRef.detectChanges()
【发布时间】:2017-08-15 18:15:19
【问题描述】:

假设我的 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 调用此 event("notification.msg") 时不会运行更改检测。

现在有两种调用变更检测的方法。

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() 中,我很好奇 性能 哪个更好?

【问题讨论】:

    标签: javascript angular angular2-changedetection


    【解决方案1】:

    ApplicationRef.tick(与setTimeout() 相同)和zone.run() 导致对整个应用程序进行更改检测。此外,在 Angular 中或由 Angular 添加的事件侦听器(使用视图绑定或@HostBinding() 会导致整个应用程序的更改检测。

    ChangeDetectorRef.detectChanges 对特定组件(及其后代,如果适用,例如由于输入绑定)运行更改检测

    如果在 Angular 区域之外运行的某些代码调用 Angular 的代码并更改状态,则需要显式调用更改检测,因为 Angular 无法知道状态已更改。

    如果状态更改是组件本地的(例如组件字段),则ChangeDetectorRef.detectChangesChangeDetectorRef.markforCheck 更有效。

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

    【讨论】:

      【解决方案2】:

      两者是完全不同的东西。

      NgZone 是一个为您的应用提供区域的库,因此您可以将实例运行到多个范围内。

      ChangeDetection 总是从父节点到叶节点 A > B > C 当您调用 detectChanges() 时,它也会调用当前组件及其子组件。所以这是对叶组件使用 OnPush changesdetectionStrategy 的最佳方法,因此它们只会在输入更新时检测Changes。

      另外,ApplicationRef 类似于 ChangeDetector;不同之处在于它会检测从根组件到最后一个子组件的变化。

      ChaneDetection 和 NgZone 是避免不必要的 ChangeDetection 的最佳组合

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-11-04
        • 2018-08-19
        • 1970-01-01
        • 1970-01-01
        • 2016-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多