Javascript 使用API中的异步数据的ngFor和trackBy仍在重新呈现DOM?
我想将Javascript 使用API中的异步数据的ngFor和trackBy仍在重新呈现DOM?,javascript,angular,rxjs,ngfor,Javascript,Angular,Rxjs,Ngfor,我想将ngFor与async数据(从API加载)和trackBy一起使用,以提高性能并在数据更新时更新列表,而不使DOM闪烁/闪烁 如果数据是静态的,则一切正常。但是当我尝试使用从API加载的数据时-trackBy不起作用 居住 来自API: 静态数据: 组成部分 导出类AppComponent{ 构造函数(私有http:HttpClient){} comments$:Observable=this.http.get(`https://jsonplaceholder.typicode.com/c
ngFor
与async
数据(从API加载)和trackBy
一起使用,以提高性能并在数据更新时更新列表,而不使DOM闪烁/闪烁
如果数据是静态的,则一切正常。但是当我尝试使用从API加载的数据时-trackBy
不起作用
居住
来自API:静态数据: 组成部分
导出类AppComponent{
构造函数(私有http:HttpClient){}
comments$:Observable=this.http.get(`https://jsonplaceholder.typicode.com/comments?_start=0&_limit=5`);
添加(){
this.comments$=this.http.get(`https://jsonplaceholder.typicode.com/comments?_start=0&_limit=6`);
}
编辑(){
this.comments$=this.comments$.pipe(
地图(评论=>{
comments.map(comment=>{
如果(comment.id==5){comment.name='edit';}
回复评论;
});
返回评论;
})
);
}
itemTrackBy(索引:编号,项目:注释){
返回item.id;
}
}
接口注释{
职位;
身份证件
电子邮件;
名称
身体;
}
模板
Make 6
或
编辑第五元素
-
{{comment.id}-{{comment.name}
发生这种情况是因为您正在更改另一个可观察实例的可观察性。ngFor在设置新的可观察对象时检测到重新呈现dom。正确的工作方式是不设置新的可观察对象,而只是在可观察对象上推送新项目
下面是一个应用此方法的stackblitz示例,您将看到dom不会重新呈现:
我不知道为什么带有静态数据的示例没有重新呈现dom,可能是整个操作为“同步”时的副作用,因为如果我在of()之后添加一个delay(),如:
您将看到它将重新渲染项目
我们可以问angular团队,为什么在不应用延迟()的情况下不重新渲染,我不知道
希望这有帮助 发生这种情况是因为您正在为另一个可观察实例更改您的可观察对象。ngFor在设置新的可观察对象时检测到重新呈现dom。正确的工作方式是不设置新的可观察对象,而只是在可观察对象上推送新项目 下面是一个应用此方法的stackblitz示例,您将看到dom不会重新呈现: 我不知道为什么带有静态数据的示例没有重新呈现dom,可能是整个操作为“同步”时的副作用,因为如果我在of()之后添加一个delay(),如: 您将看到它将重新渲染项目 我们可以问angular团队,为什么在不应用延迟()的情况下不重新渲染,我不知道
希望这有帮助 非常感谢你的帮助!我发现您的代码在没有设置新的变更检测策略的情况下运行良好。在这种情况下有必要吗?我很高兴它有帮助:)。您的意思是使用onPush还是默认的更改检测策略?在本例中,没有输入,因此两种策略将给出相同的结果。虽然,默认情况下在所有组件上使用onPush是一种很好的做法。非常感谢您的帮助!我发现您的代码在没有设置新的变更检测策略的情况下运行良好。在这种情况下有必要吗?我很高兴它有帮助:)。您的意思是使用onPush还是默认的更改检测策略?在本例中,没有输入,因此两种策略将给出相同的结果。不过,默认情况下在所有组件上使用onPush是一种良好的做法。
export class AppComponent {
constructor(private http: HttpClient){}
comments$: Observable<Comment[]> = this.http.get<Comment[]>(`https://jsonplaceholder.typicode.com/comments?_start=0&_limit=5`);
add() {
this.comments$ = this.http.get<Comment[]>(`https://jsonplaceholder.typicode.com/comments?_start=0&_limit=6`);
}
edit() {
this.comments$ = this.comments$.pipe(
map(comments => {
comments.map( comment => {
if(comment.id === 5){ comment.name = 'edit'; }
return comment;
});
return comments;
})
);
}
itemTrackBy(index: number, item: Comment) {
return item.id;
}
}
interface Comment {
postId;
id;
email;
name;
body;
}
<button (click)="add()">Make 6</button>
OR
<button (click)="edit()">edit 5-th element</button>
<ul>
<li *ngFor="let comment of (comments$ | async); trackBy: itemTrackBy">
{{comment.id}} - {{comment.name}}
</li>
</ul>
this.episodes = of([
{id: 1, name: "name1"},
{id: 2, name: "name2"}
]).pipe(delay(100));