Angular2 zone.run()vs ChangeDetectorRef.detectChanges()

Aje*_*jey 26 javascript angular2-changedetection angular

假设我function noificationHandler()在我的service.ts中有一个超出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);
    }
Run Code Online (Sandbox Code Playgroud)

component.ts

constructor(private service: myService) {
    this.service.myObservable.subscribe(list => {
        this.list = list;
    });
}
Run Code Online (Sandbox Code Playgroud)

此时^^^模板未使用新数据更新

由于"notification.msg"它位于角度区域之外,因此("notification.msg")在调用此事件时不会运行角度变化检测.

现在有两种方法可以调用变化检测.

1)通过包装noificationHandler()angular的zone.run()的内部

 this.registry.subscribe("a2mevent.notification.msg", this.ngZone.run(() => this.noificationHandler.bind(this)));
Run Code Online (Sandbox Code Playgroud)

2)通过单独要求组件检测变化

constructor(private service: myService, private ref: ChangeDetectorRef) {
    this.service.myObservable.subscribe(list => {
        this.list = list;
        this.ref.detectChanges(); // <==== manually invoking change detection
    });
}
Run Code Online (Sandbox Code Playgroud)

这两个选项都有效!我的组件结构如下

A --> root component
B
C
D // my component is here (4 levels of nesting)
Run Code Online (Sandbox Code Playgroud)

问题 -

1)detectChanges()是否仅检测其自身组件的更改,还是会对子组件运行更改检测?

2)zone.run()会触发从根到叶子的所有组件的变化检测吗?

在zone.run()和detectChanges()中,我很好奇哪个性能更好?

Gün*_*uer 27

ApplicationRef.tick(与setTimeout())相同,并zone.run()在整个应用程序中引起变化检测.此外,还在Angular或Angular中添加了事件侦听器(使用视图绑定或@HostBinding()对整个应用程序进行更改检测).

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

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

如果对状态的更改是组件的本地(例如组件字段),ChangeDetectorRef.detectChanges或者ChangeDetectorRef.markforCheck更有效.

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


Uma*_*nis 6

两者都完全不同.

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

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

另外,ApplicationRef类似于ChangeDetector; 区别在于它将检测从根组件到最后一个子组件的更改.

ChaneDetection和NgZone是最好的组合,总是避免不必要的ChangeDetection