angular - markForCheck() 和 detectChanges() 有什么区别

标签 angular angular2-changedetection

ChangeDetectorRef.markForCheck()有什么区别和 ChangeDetectorRef.detectChanges() ?

我只有found information on SO关于NgZone.run()的区别,但不在这两个函数之间。

对于仅引用文档的答案,请举例说明一些实际情况以选择其中之一。

最佳答案

detectChanges() : void

Checks the change detector and its children.


这意味着,如果您的模型(您的类)中的任何内容发生了更改但未反射(reflect) View 的情况,您可能需要通知 Angular 检测这些更改(检测本地更改)并更新 View 。
可能的情况可能是:
1- 变更检测器从 View 中分离(见 detach)
2- 发生了更新,但它不在 Angular Zone 内,因此,Angular 不知道它。
就像当第三方函数更新了您的模型并且您想在此之后更新 View 时一样。
 someFunctionThatIsRunByAThirdPartyCode(){
     yourModel.text = "new text";
 }
因为此代码在 Angular 的区域之外(可能),您很可能需要确保检测更改并更新 View ,因此:
 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);
 }
3- 也有在 change detection cycle 之后更新模型的情况已完成,在这些情况下,您会收到这个可怕的错误:
"检查后表达有变化";
这通常意味着(来自 Angular2 语言):
我看到您的模型发生了变化,这是由我接受的一种方式(事件、XHR 请求、setTimeout 和 ...)引起的,然后我运行了更改检测以更新您的 View 并完成了它,但是还有另一个您的代码中的函数再次更新了模型,我不想再次运行我的更改检测,因为不再像 AngularJS 那样进行脏检查:D,我们应该使用单向数据流!
你肯定会遇到这个错误 :P 。
修复它的几种方法:
1- 正道 :确保更新在变更检测周期内(Angular2 更新是发生一次的一种方式,之后不要更新模型并将代码移动到更好的位置/时间)。
2- 懒人方式 :在该更新之后运行detectChanges() 以使angular2 满意,这绝对不是最好的方法,但是当您询问可能的情况是什么时,这是其中之一。
这样你说:我真诚地知道你运行了更改检测,但我希望你再做一次,因为在你完成检查后我不得不动态更新一些东西。
3- 将代码放入 setTimeout , 因为 setTimeout由区域修补并将运行 detectChanges完成后。

从文档
markForCheck() : void

Marks all ChangeDetectionStrategy ancestors as to be checked.


这在 时最需要变更检测策略 您的组件是 OnPush .
OnPush 本身意味着,只有在发生以下任何一种情况时才运行更改检测:
1- 组件的@inputs 之一已完全替换为新值,或者简单地说,如果@Input 属性的引用完全更改。
所以如果 变更检测策略 您的组件是 OnPush 然后你有:
   var obj = {
     name:'Milad'
   };
然后你更新/变异它像:
  obj.name = "a new name";
这不会更新 obj 引用,因此不会运行更改检测,因此 View 不会反射(reflect)更新/变异。
在这种情况下,您必须手动告诉 Angular 检查和更新 View (markForCheck);
所以如果你这样做:
  obj.name = "a new name";
你需要这样做:
  this.cd.markForCheck();
相反,下面会导致运行更改检测:
    obj = {
      name:"a new name"
    };
用新的 {} 完全取代了之前的 obj ;
2- 事件已触发,例如单击或类似事件,或任何子组件已发出事件。
事件如:
  • 点击
  • 键盘注册
  • 订阅事件

  • 简而言之:
  • 使用 detectChanges()当您在 angular 运行后更新模型时,它会进行更改检测,或者如果更新根本不在 angular 世界中。
  • 使用 markForCheck()如果您使用 OnPush 并且绕过了 ChangeDetectionStrategy通过改变一些数据或者你已经更新了 中的模型设置超时 ;
  • 关于angular - markForCheck() 和 detectChanges() 有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41364386/

    相关文章:

    angular - 使用 Reactive Forms 和 ChangeDetectionStrategy.OnPush 显示验证消息

    javascript - 在模板中使用 Angular Reactive Forms .get() 方法会导致不必要的方法调用,如组件方法吗?

    即使使用 ChangeDetectionStrategy.OnPush 也会调用 Angular ngDoCheck()

    javascript - 尽管在区域外运行超时,Chrome DevTools 中的 NgZone 超时警告

    javascript - 当我使用 'Promise' 命令时找不到名称 'npm start' 错误

    同时运行 ng build --watch 和 ngserve 时,Angular 7 库 html 模板更改不会影响应用程序

    javascript - 路由不适用于捆绑的(webpack)Angular 2 项目

    html - Angular 7 不呈现 Bootstrap 控制

    angular - 如何在 Observable 中返回模拟数据?

    javascript - Clockify 中的登录表单