Angular 9将新项目添加到列表而不刷新列表

Posted

技术标签:

【中文标题】Angular 9将新项目添加到列表而不刷新列表【英文标题】:Angular 9 Add new item to list without refreshing list 【发布时间】:2020-09-04 03:34:49 【问题描述】:

我正在开发一个角度应用程序,我可以说我是角度方面的新手。在我的应用程序中,我通过带有可观察数组的 httpclient 将来自服务器的数据绑定到如下所示的基本列表。我添加了一个新项目以在不同的组件中列出。列表组件和添加新项目组件都在同一页面上。

我对绑定数据和添加新数据没有任何问题。添加新项目后出现问题。在我将新项目添加到列表的数据源后,整个组件都会刷新;但我不想要这个,我想添加新元素而不刷新列表。

简化代码在这里。 我的包含列表的组件:

 export class GroupSetupComponent implements OnInit 
  dataSet$: Observable<Group[]>;

  constructor (private groupService : GroupService) 

  ngOnInit(): void 
    this.getGroups();
   

  getGroups() 
    this.dataSet$ = this.groupService.getGroups();
  

  refreshGroupList(group: Group) 
    if(group) 
      // I have tried getting all list from database again
      // this.getGroups();

      // than I tried to add new item to existing observable array
      this.dataSet$ = this.dataSet$.
      pipe(
        map(data =>
          
            data.push(group);
            return dataSet;
          ));
    
  

及组件模板:

<div *ngIf="dataSet$ | async as resultSet;">
<mat-card>
    <mat-card-content>
        <mat-selection-list>
            <mat-list-option *ngFor="let item of resultSet;" [value]="item.id" [disableRipple]="true">
                item.name
            </mat-list-option>
        </mat-selection-list>
    </mat-card-content>
</mat-card></div>

refreshGroupList 函数是在将新项目添加到数据库并从 api 获取成功消息后从子组件触发的。

我想问,我的做法对不对?如果不是,那么在列表上执行这种 crud 操作的有效方法是什么?

【问题讨论】:

也许你想使用trackBy?见这篇文章:medium.com/better-programming/… 【参考方案1】:

您可以将其添加到您的组件中

   byId(index, item) 
      return item.id;
   

并修改ngFor

<mat-list-option *ngFor="let item of resultSet; trackBy: byId" [value]="item.id" [disableRipple]="true">
                item.name
            </mat-list-option>

通过提供 trackBy 键,Angular 将检查每个项目并按 ID 进行差异,而不是刷新整个数组。如果您打开开发人员工具并检查元素,您会注意到只有新添加的项目才会获得 dom 更新。

更新---- 您可以尝试如下更改您的实现,因此您的流引用保持不变,看看是否可以解决问题

dataSet$=new BehaviorSubject([])
ngOnInit(): void 
    this.getGroups().subscribe(group=>dataSet$.next(group));
   

refreshGroupList(group)
     this.dataSet$.next(this.dataSet$.value.concat(group))

【讨论】:

感谢您的回答,我认为这就是重点;但不幸的是,添加新项目后它仍然是刷新列表。使用异步管道和可观察效果吗? dataSet$ 是我真正的数据源,我将项目添加到此属性,而不是结果集。这个效果如何? dataSet$ 是否有时会返回 falsy 或者它总是产生项目?理论上它不应该受到 *ngIf 的影响,除非它从 false 变为 true 和 true 到 false 等。 我不这么认为它会从 false 变为 true 。在 refreshGroupList 函数中一切正常吗?我基本上只是在当前列表中添加一个新项目。 您的 refreshGroupList 不是一个理想的解决方案,但它仍然不应该导致整个列表刷新。你可以试试行为主体实现【参考方案2】:

您可以在组件 ChangeDetection: OnPush 上进行设置,并使用 ChangeDetecionRef 服务和方法 markToCheck() 手动告知何时刷新组件。

【讨论】:

以上是关于Angular 9将新项目添加到列表而不刷新列表的主要内容,如果未能解决你的问题,请参考以下文章

Angular 2 - ngFor while index < x

弹出后的离子刷新列表

使用 jQuery UI 可排序插件添加项目后刷新列表

将列表视图滚动到新添加项目的位置

notifyDataSetChanged()使列表刷新并滚动回到顶部

将拖动的项目转换为可放置的