ChangeDetectionStrategy.OnPush 打破了 ControlValueAccessor 的禁用状态

Posted

技术标签:

【中文标题】ChangeDetectionStrategy.OnPush 打破了 ControlValueAccessor 的禁用状态【英文标题】:ChangeDetectionStrategy.OnPush breaks the disabled state of a ControlValueAccessor 【发布时间】:2019-01-28 12:52:26 【问题描述】:

在我的 Angular 应用程序中,我通过实现 ControlValueAccessor 接口创建了一个自定义表单元素。

所以在我的组件中,我正确实现了该接口的所有方法,包括setDisabledState

/**
 * This function is called when the control status changes to or from "disabled".
 * Depending on the value, it will enable or disable the appropriate DOM element.
 *
 * @param isDisabled
 */
setDisabledState(isDisabled: boolean): void 
  this.disabled = isDisabled;

一切正常。

问题是当我将组件的ChangeDetectionStrategy 设置为OnPush 时。

这样做会破坏我的组件的启用/禁用功能。

【问题讨论】:

【参考方案1】:

OnPush 只有在我们谈论父/子组件通信时才有意义。当孩子有 changeDetection: ChangeDetectionStrategy.OnPush 设置并且父母将对象作为输入传递给孩子时。

如果您正在创建具有自己状态的反应式自定义表单控件。最好避免使用 onPush。如果你想使用,你可以使用 cdr.markforCheck() 手动调用 Change detection。

【讨论】:

感谢您的建议,但就我而言,我只是想解决图书馆现有组件的问题。所以改变变化检测策略不是我的决定:github.com/valor-software/ngx-bootstrap/issues/4055【参考方案2】:

可以通过手动触发变更检测来解决问题。

我们需要将ChangeDetectorRef 注入到我们的组件中:

import   ChangeDetectorRef  from '@angular/core';

// ...

constructor(
  private cd: ChangeDetectorRef,
)  

然后在启用/禁用状态更改时使用它手动触发更改检测:

setDisabledState(isDisabled: boolean): void 
  this.disabled = isDisabled;
  this.cd.markForCheck(); // this will manually trigger the change detection

【讨论】:

以上是关于ChangeDetectionStrategy.OnPush 打破了 ControlValueAccessor 的禁用状态的主要内容,如果未能解决你的问题,请参考以下文章