我只有found information on S.O关于NgZone.run()之间的区别,但不是在这两个函数之间.
对于仅仅参考文献的答案,请说明一些实际的情景,选择一个?这将有助于在我的脑海中澄清.
detectChanges() : void
Checks the change detector and its children.
如果您的模型(您的类)中的任何内容已更改但尚未反映视图的情况,则可能需要通知Angular才能检测到这些更改(检测本地更改)并更新视图.
可能的情况可能是:
1-变化检测器与视图分离(见detach)
2-更新已经发生,但它没有在角度区域内,因此Angular不知道.
就像第三方功能更新您的模型,并且您想要更新视图之后.
someFunctionThatIsRunByAThirdPartyCode(){ yourModel.text = "new text"; }
因为这个代码在Angular的区域之外(大概),你很可能需要确保检测更改并更新视图,所以:
myFunction(){ someFunctionThatIsRunByAThirdPartyCode(); // Let's detect the changes that above function made to the model which Angular is not aware of. this.cd.detectChanges(); }
注意 :
还有其他的方法可以做出上述的工作,换句话说,还有其他的方法可以在Angular变化周期内引发变化.
**你可以在zone.run中包装第三方功能:
myFunction(){ this.zone.run(this.someFunctionThatIsRunByAThirdPartyCode); }
**可以将函数包装在setTimeout中:
myFunction(){ setTimeout(this.someFunctionThatIsRunByAThirdPartyCode,0); }
在更改检测周期完成之后,还有更新模型的情况,在这些情况下,您会得到这个可怕的错误:
“检查后表情已经改变”;
这通常意味着(来自Angular2语言):
我看到您的模型更新是由我接受的方式(事件,XHR请求,setTimeout和…)引起的,然后我运行我的更改检测更新您的视图,我完成了,但是另有一个在您的代码中更新模型的功能,我不想再次运行我的更改检测,因为没有像AngularJS这样的脏检查:D,我们应该使用单向数据流!
你一定会遇到这个错误:P.
1-正确的方法:确保更新在更改检测之内(Angular2更新是发生一次的一种方式,不要更新模型,然后将代码移动到更好的位置/时间).
2-懒惰的方式:在更新之后运行detectChanges(),以使angular2快乐,这绝对不是最好的方法,但是当你问什么是可能的情况,这是其中之一.
这样你说的是:我真诚地知道你运行了变更检测,但是我不能再做,因为在完成检查之后,我必须在飞行中更新一些东西.
3将代码放在setTimeout中,因为setTimeout被区域修补,并在完成后运行detectChanges.
从文档
markForCheck() : void
Marks all ChangeDetectionStrategy ancestors as to be checked.
当组件的ChangeDetectionStrategy是OnPush时,这主要是需要的.
OnPush本身就意味着,只有在发生这些情况时,才能运行更改检测:
1-组件的@inputs之一已经被一个新的值完全替换,或者简单地说,如果@Input属性的引用已经完全改变了.
所以如果您的组件的ChangeDetectionStrategy是OnPush,然后你有:
var obj = { name:'Milad' };
然后你更新/变更它像:
obj.name = "a new name";
这不会更新obj引用,因此更改检测不会运行,因此视图不会反映更新/突变.
相反,波纹管将导致更改检测运行:
obj = { name:"a new name" };
其中一个新的{}完全取代了以前的obj;
所以如果你改变了这个obj,那么这个视图不会被更新,即使你运行detectChanges也不会工作,因为没有根据ChangeDetectionStrategy.OnPush进行任何修改!
在这种情况下,您必须手动告知Angular才能检查并更新视图(markForCheck);
所以如果你这样做:
obj.name = "a new name";
你需要这样做:
this.cd.markForCheck();
2-事件已经触发了,像点击或者像这样的东西,或者任何一个子组件已经发出了一个事件.
活动如:
简而言之:
>使用detectChanges()更新模型后,角度已经运行它是更改检测,或者更新还没有在角度世界.>如果您使用OnPush,请使用markForCheck(),并且您通过突变某些数据或更新了setTimeout中的模型来绕过ChangeDetectionStrategy;