【问题标题】:Triggering change detection manually in Angular在 Angular 中手动触发变更检测
【发布时间】:2016-04-22 00:10:11
【问题描述】:

我正在编写一个具有 Mode(): string 属性的 Angular 组件。

我希望能够以编程方式设置此属性,而不是响应任何事件。

问题在于,在没有浏览器事件的情况下,模板绑定 {{Mode}} 不会更新。

有没有办法手动触发这种变化检测?

【问题讨论】:

    标签: angular angular2-changedetection


    【解决方案1】:

    尝试以下方法之一:

    • ApplicationRef.tick() - 类似于 AngularJS 的 $rootScope.$digest() - 即检查完整的组件树
    • NgZone.run(callback) - 类似于 $rootScope.$apply(callback) - 即评估 Angular 区域内的回调函数。我认为,但我不确定,这最终会在执行回调函数后检查完整的组件树。
    • ChangeDetectorRef.detectChanges() - 类似于 $scope.$digest() - 即仅检查此组件及其子组件

    您可以将ApplicationRefNgZoneChangeDetectorRef 注入到您的组件中。

    【讨论】:

    • 谢谢,我选择了第三种解决方案,以免检查所有内容,因为更改已相当本地化。当我有更多时间时,我应该研究其他选项。每个选择对性能有影响吗?
    • +1 表示ChangeDetectorRef.detectChanges()。验证器在我的指令可以更新输入值之前触发。
    • ApplicationRef.tick() 和 ChangeDetectorRef.detectChanges() 仍然存在于 2.0.0 final 中。
    • 只是想我会提到这一点。这些不是静态方法,它们是实例方法。您需要将这些类作为服务注入。
    • ApplicationRef.tick() 帮助解决了 FireFox v17 的问题 (
    【解决方案2】:

    我使用了公认的答案参考并想举一个例子,因为 Angular 2 文档非常难以阅读,我希望这更容易:

    1. 导入NgZone:

      import { Component, NgZone } from '@angular/core';
      
    2. 将其添加到您的类构造函数中

      constructor(public zone: NgZone, ...args){}
      
    3. 使用zone.run运行代码:

      this.zone.run(() => this.donations = donations)
      

    【讨论】:

    • 你应该把zone.run代码放在哪里,donations到底是什么?
    • @suku 捐赠是您要更新的任何属性,因此可能是 this.foo = bar。 zone.run 去任何你想更新东西的地方。
    • 我在使用 document.addEventListener("resume", callback) 时使用了这个解决方案来强制更新视图
    【解决方案3】:

    我可以用markForCheck()更新它

    导入 ChangeDetectorRef

    import { ChangeDetectorRef } from '@angular/core';
    

    注入并实例化它

    constructor(private ref: ChangeDetectorRef) { 
    }
    

    最后标记更改检测发生

    this.ref.markForCheck();
    

    这是一个示例,其中 markForCheck() 有效,而 detectChanges() 无效。

    https://plnkr.co/edit/RfJwHqEVJcMU9ku9XNE7?p=preview

    编辑:这个例子不再描述这个问题:(我相信它可能正在运行一个更新的 Angular 版本。

    (按 STOP/RUN 再次运行)

    【讨论】:

    • detectChanges() 无法正常工作。我注意到了同样的问题,并发现如果更改检测不是 OnPush,它就可以工作。最好能得到一个解释......
    • 看起来 detectChanges 实际上在这个 plunker 中工作?我错过了什么吗?
    • 您应该注意 ChangeDetectorRef 仅适用于组件
    • (!) 这是一个不好的例子,我很抱歉。示例没有显示任何内容。第一项只是被覆盖。稍微调整一下计时器...
    • 这个例子不再描述问题了 :( 我相信它可能正在运行一个更新的 Angular 版本。
    【解决方案4】:

    在 Angular 2+ 中,尝试使用 @Input 装饰器

    它允许在父组件和子组件之间进行一些很好的属性绑定。

    首先在父级中创建一个全局变量来保存对象/属性 会传给孩子。

    接下来在子进程中创建一个全局变量来保存传递的对象/属性 来自父母。

    然后在使用子模板的父html中,添加方括号 使用子变量的名称表示,然后将其设置为等于名称 的父变量。示例:

    <child-component-template [childVariable] = parentVariable>
    </child-component-template>
    

    最后,在子组件中定义子属性的地方,添加 输入装饰器:

    @Input()
    public childVariable: any
    

    当你的父变量更新时,它应该将更新传递给子组件,子组件将更新它的 html。

    另外,要在子组件中触发函数,请查看 ngOnChanges。

    【讨论】:

    • 不...这就是问题...如果您在父项中更新...例如以静态方法“通过引用”更新,孩子不会将其拾取,因为没有更改检测发生
    • 我这几天也遇到了同样的问题。我尝试从 PHP 后端检索数据,但数据根本没有更新。在 Microsoft Edge 上运行良好,但在其他浏览器上却不行。我一直在获取我第一次开始时的数据,但如果数据发生变化,它不会在视图中更新
    【解决方案5】:

    ChangeDetectorRef.detectChanges() - 类似于 $scope.$digest() - 即只检查这个组件及其子组件

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-17
      • 1970-01-01
      • 1970-01-01
      • 2021-03-28
      • 2018-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多