Angular @Input在有变化时不更新UI



我有一个接收Input的子组件。这个值是从我在onChanges中检查过的父元素改变的,它正在改变,但是我在UI上的输入的基础上做了一些决策,但它没有反映。

@Component({
selector: 'parent',
templateUrl: './parent.html',
styleUrls: ['./parent.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
{
hasData(value: string): boolean {
return value === 'hasData'
}
}

@Component({
selector: 'child',
templateUrl: './child.html',
styleUrls: ['./child.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildComponent{
@Input() hasData= false;
}

父元素设计:

<child
[hasData]="hasData(data.id)"
>
</child>

孩子的设计:

<img *ngIf="hasData" src="data.png" alt="data" />

到目前为止,我已经尝试了ngOnChanges,并且输入值正在正确更新。

正如许多其他人已经指出的那样,问题是您已经将变更检测策略分配给了两个组件上的OnPushOnPush告诉Angular只检查更新

  • @Input-引用发生变化时,如注释
  • 所指出的
  • 事件发生,如按钮点击
  • 手动触发变更检测时

在您的例子中,您传递的是一个布尔值(原始值),它是按值传递的,而不是按引用传递的,因此不会触发更新。

这里有一个Stackblitz来说明这个问题。

要解决这个问题,您有几个不同的选项。

使用markForCheck

当值更新时,将组件标记为包含在将更新输入的变更检测周期中。

使用async管道与可观察对象

这基本上是markForCheck的内置版本,因为当async被触发时运行的代码将组件标记为markForCheck的更改检测检查。(你可以在这里查看源代码)

在旁注中,正如有人已经指出的那样,在模板中使用函数调用被认为是不好的做法,因为它可能会对性能产生严重影响。考虑用async管道代替[hasData]="hasData(data.id)",并使用某种可观察对象。

最新更新