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

rvpgvaaj  于 2023-05-05  发布在  Java
关注(0)|答案(5)|浏览(200)

我已经实现了一个子组件,用于根据@Input()提供的列表呈现一个表。数据是通过http加载的,但是UI(子组件)不会更新,除非我在屏幕上挥动鼠标。我看到有人在我的孩子身上实现ngOnChanges(),但我认为Angular应该默认做到这一点?我错过什么了吗?为什么UI不更新呢?
子代码看起来像这样:

child.component.ts

@Component({
  selector: 'child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.scss'],
})
export class ChildComponent implements {
  @Input() data: any[] = [];
  constructor() {}
}

child.component.html

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

使用组件的父代码看起来像这样:

parent.component.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;
    });
  }
}

parent.component.html

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

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

我验证了只有在subscribe回调中更新时才会加载失败(如果我设置了一个静态数组,它加载得很好)。
所以看起来我可以通过在父组件中运行changeDetectorRef.detectChanges()来解决这个问题,但这感觉有点像我不应该这样做。这是解决问题的好办法吗?或者这是否表明我的实现有问题?

parent.component.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();
    });
  }
}
bksxznpy

bksxznpy1#

似乎你在模板表达式中有一些其他的错误,这些错误迫使整个模板失败。这是我创建的stackblitz,一切正常:https://stackblitz.com/edit/angular-ivy-w2ptbb?file=src%2Fapp%2Fhello.component.ts
你有可能在控制台的一些错误?

kiz8lqtg

kiz8lqtg2#

我用一个静态字符串数组替换了这个服务,它工作得很好。我认为可观察订阅有问题。

child.component.ts

import { Component, OnInit,Input } from '@angular/core';

@Component({
  selector: 'child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
@Input() data: any[] = [];
  constructor() { }

  ngOnInit() {
  }

}

parent.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css'],
})
export class ParentComponent implements OnInit {
  data: string[] = [];

  constructor() {}

  ngOnInit() {
    
      this.data = ['hello', 'world','aaa','ddd'];
    
  }
}
yrdbyhpb

yrdbyhpb3#

我已经修复了这个问题,更新了传递给子输入的属性,而不是重新分配它。我认为Angular将输入作为副本传递。所以,在subscribe body中你应该使用

resultOfSubscribe.forEach((v) => varPassedByInput.push(v));
vi4fp9gy

vi4fp9gy4#

您还可以尝试通过强制值引用更新来强制更改检测,例如,通过spread运算符:

this.endpointService.loadData().subscribe((response) => {
  this.data = [...response];
});
lrl1mhuk

lrl1mhuk5#

嗯嗯..当组件第一次呈现时,它将显示空数组,因为API调用仍在发生,并且需要子组件中的onchanges方法以侦听完整的api调用,并且列表将重新呈现

相关问题