Angular Dart中对象列表展示最佳方式及Redux场景下数据访问实现问询
解决方案:结合Angular的trackBy与Redux Immutable特性实现高效列表渲染
针对你的场景——Redux Store中以Immutable方式管理项数据(更新时生成副本),同时希望仅在选中项集合变化时重建列表,而项内容更新时仅刷新对应DOM内容——我们可以通过以下步骤实现:
1. 核心思路
Redux的Immutable更新会让每次项内容变更都生成新对象,如果直接用这些对象作为ngFor的数据源,会导致列表频繁重建。所以我们需要:
- 用**选中项的唯一标识(如ID)**作为列表的跟踪依据,确保只有选中项的集合变化时才触发列表重建
- 通过标识从全量项Map中实时获取最新的项内容,保证展示的是最新数据
2. 组件内数据处理
首先从Redux Store中获取两个Observable数据:
allItems$: 所有项的Map(键为项的唯一ID)selectedItemIds$: 当前选中项的ID数组
然后组合这两个Observable,生成供ngFor使用的选中项列表:
import { Component } from '@angular/core'; import { Observable, combineLatest } from 'rxjs'; import { map } from 'rxjs/operators'; import { Store } from '@ngrx/store'; // 假设用NgRx,其他Redux实现同理 import { AppState, Item } from './your-state-types'; @Component({ selector: 'app-selected-items-list', templateUrl: './selected-items-list.component.html' }) export class SelectedItemsListComponent { // 从Store获取数据 allItems$: Observable<Map<string, Item>> = this.store.select(state => state.items.all); selectedItemIds$: Observable<string[]> = this.store.select(state => state.items.selectedIds); // 组合生成选中项列表Observable selectedItems$: Observable<Item[]> = combineLatest([this.allItems$, this.selectedItemIds$]).pipe( map(([allItemsMap, selectedIds]) => { // 根据ID从Map中取最新项,过滤掉不存在的项 return selectedIds .map(id => allItemsMap.get(id)) .filter(item => item !== undefined); }) ); constructor(private store: Store<AppState>) {} // 定义trackBy函数,用项的ID作为跟踪键 trackByItemId(index: number, item: Item): string { return item.id; } }
3. 模板中使用ngFor
在HTML模板中,使用async管道订阅Observable,并指定trackBy函数:
<ul class="selected-items"> <li *ngFor="let item of selectedItems$ | async; trackBy: trackByItemId" class="item-entry" > <!-- 这里会自动显示项的最新内容 --> <h3>{{ item.title }}</h3> <p>{{ item.description }}</p> </li> </ul>
4. 为什么这样有效?
combineLatest:当allItems$或selectedItemIds$任一更新时,都会重新计算选中项列表,确保我们总是拿到最新的项数据trackBy:告诉Angular用项的ID来识别列表项,即使项对象是Redux生成的新副本(内容更新),只要ID不变,Angular不会重新创建<li>元素,只会更新内部的DOM内容- 仅在选中项变化时重建列表:只有当
selectedItemIds$数组发生变化(新增/移除选中项),ngFor才会添加/移除对应的<li>元素,完全符合你的需求
注意事项
- 确保你的
Item类型有唯一的标识字段(如id),如果用其他唯一值替换即可 - 加入
filter(item => item !== undefined)是为了避免当选中ID在全量Map中不存在时,模板出现错误 - 不要在模板中直接调用函数生成Observable(比如
*ngFor="let item of getSelectedItems() | async"),定义成组件属性selectedItems$更高效,避免变更检测时重复执行函数
内容的提问来源于stack exchange,提问作者Fabian
相关产品推荐
相关产品推荐

