我已经实现了一个子组件,用于根据@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();
});
}
}
5条答案
按热度按时间bksxznpy1#
似乎你在模板表达式中有一些其他的错误,这些错误迫使整个模板失败。这是我创建的stackblitz,一切正常:https://stackblitz.com/edit/angular-ivy-w2ptbb?file=src%2Fapp%2Fhello.component.ts
你有可能在控制台的一些错误?
kiz8lqtg2#
我用一个静态字符串数组替换了这个服务,它工作得很好。我认为可观察订阅有问题。
child.component.ts
parent.component.ts
yrdbyhpb3#
我已经修复了这个问题,更新了传递给子输入的属性,而不是重新分配它。我认为Angular将输入作为副本传递。所以,在subscribe body中你应该使用
vi4fp9gy4#
您还可以尝试通过强制值引用更新来强制更改检测,例如,通过spread运算符:
lrl1mhuk5#
嗯嗯..当组件第一次呈现时,它将显示空数组,因为API调用仍在发生,并且需要子组件中的onchanges方法以侦听完整的api调用,并且列表将重新呈现