Angular @Input() 不更新子级中的 UI

我已经实现了一个子组件来根据通过 @Input() 提供的列表来呈现表格。数据是通过 http 加载的,但是除非我在屏幕上挥动鼠标,否则 UI(子组件)不会更新。我见过有人发布关于在我的孩子中实现 ngOnChanges() 的帖子,但我认为 Angular 应该默认这样做?我错过了什么吗?为什么 UI 不会随之更新?


子代码看起来像这样:


子组件.ts


@Component({

  selector: 'child',

  templateUrl: './child.component.html',

  styleUrls: ['./child.component.scss'],

})

export class ChildComponent implements {

  @Input() data: any[] = [];

  constructor() {}

}

子组件.html


<table>

  <tr *ngFor="let item of data"><td>{{ item }}</td></tr>

</table>

使用该组件的父代码如下所示:


父组件.ts


@Component({

  selector: 'parent',

  templateUrl: './parent.component.html',

  styleUrls: ['./parent.component.scss'],

})

export class ParentComponent implements OnInit {

  data: string[] = [];


  constructor(private endpointService: EndpointService) {}


  ngOnInit() {

    // response is a string array like: ['hello', 'world']

    this.endpointService.loadData().subscribe((response) => {

      this.data = response;

    });

  }

}

父组件.html


<child [data]="data"></child>

=============================编辑==================== =============


我验证了它仅在订阅回调内部更新时才加载失败(如果我设置静态数组,它加载得很好)。


所以看起来我可以通过在父组件中运行changeDetectorRef.detectChanges()来解决这个问题,但这感觉很黑客,就像我不应该这样做一样。这是解决这个问题的好方法吗?或者这是否表明我的实现有问题?


父组件.ts


@Component({

  selector: 'parent',

  templateUrl: './parent.component.html',

  styleUrls: ['./parent.component.scss'],

})

export class ParentComponent implements OnInit {

  data: string[] = [];


  constructor(private endpointService: EndpointService,

              private changeDetectorRef: ChangeDetectorRef) {}


  ngOnInit() {

    // response is a string array like: ['hello', 'world']

    this.endpointService.loadData().subscribe((response) => {

      this.data = response;

      this.changeDetectorRef.detectChanges();

    });

  }

}


慕容森
浏览 138回答 4
4回答

一只名叫tom的猫

您还可以尝试通过强制值引用更新来强制更改检测,例如通过扩展运算符:this.endpointService.loadData().subscribe((response)&nbsp;=>&nbsp;{ &nbsp;&nbsp;this.data&nbsp;=&nbsp;[...response]; });

回首忆惘然

我已经解决了这个问题,更新了子输入传递的属性,而不是重新分配它。我认为 Angular 将输入作为副本传递。所以,在订阅正文中你应该使用resultOfSubscribe.forEach((v)&nbsp;=>&nbsp;varPassedByInput.push(v));

隔江千里

我用静态字符串数组替换了该服务,效果很好。我认为可观察订阅有问题。子组件.tsimport { Component, OnInit,Input } from '@angular/core';@Component({&nbsp; selector: 'child',&nbsp; templateUrl: './child.component.html',&nbsp; styleUrls: ['./child.component.css']})export class ChildComponent implements OnInit {@Input() data: any[] = [];&nbsp; constructor() { }&nbsp; ngOnInit() {&nbsp; }}父组件.tsimport { Component, OnInit } from '@angular/core';@Component({&nbsp; selector: 'parent',&nbsp; templateUrl: './parent.component.html',&nbsp; styleUrls: ['./parent.component.css'],})export class ParentComponent implements OnInit {&nbsp; data: string[] = [];&nbsp; constructor() {}&nbsp; ngOnInit() {&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; this.data = ['hello', 'world','aaa','ddd'];&nbsp; &nbsp;&nbsp;&nbsp; }}

波斯汪

模板表达式中似乎存在一些其他错误,导致整个模板失败。这是我创建的 stackblitz,一切正常:https://stackblitz.com/edit/angular-ivy-w2ptbb ?file=src%2Fapp%2Fhello.component.ts您在控制台中可能有一些错误吗?
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript