You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular中*ngFor构建DOM:逐次还是批量渲染?如何优化?

Angular 大列表渲染问题解答

1. *ngFor 的 DOM 渲染方式

Angular 处理 *ngFor 时,不会逐次迭代就把元素添加到 DOM。它会先在内存中构建所有子项的视图结构,等整个变更检测周期完成后,再一次性把所有生成的 DOM 节点批量插入页面——这和原生 DocumentFragment 的核心思路一致,都是为了减少 DOM 重排重绘的次数。

你觉得循环耗时,主要是数千个子项的视图创建、数据绑定本身消耗计算资源,而非 DOM 逐次插入导致的性能损耗。

2. 大列表性能优化方案

虚拟滚动(最优方案)

如果是数千甚至上万个列表项,最有效的优化是用虚拟滚动:只渲染当前视口内的元素,滚动时动态替换可见区域的内容,大幅减少 DOM 节点数量。Angular 官方 CDK 组件库提供了现成的实现,示例代码如下:

<cdk-virtual-scroll-viewport itemSize="50">
  <div *cdkVirtualFor="let item of items; index as i">
    {{i}} - {{item.title}}
  </div>
</cdk-virtual-scroll-viewport>

只需引入 ScrollingModule,设置每个列表项的固定高度 itemSize,就能显著降低渲染压力。

分批渲染

如果不想用虚拟滚动,也可以把数据分成多批,分多次渲染到 DOM,避免单次渲染占用过多资源。比如用 requestAnimationFrame 分批加载:

// 组件逻辑
items: any[] = [];
batchSize = 100;
currentIndex = 0;
allItems: any[] = []; // 你的完整数据列表

loadBatch() {
  const batch = this.allItems.slice(this.currentIndex, this.currentIndex + this.batchSize);
  this.items.push(...batch);
  this.currentIndex += this.batchSize;
  if (this.currentIndex < this.allItems.length) {
    requestAnimationFrame(() => this.loadBatch());
  }
}

ngOnInit() {
  this.loadBatch();
}

每次只渲染100条,给浏览器留足处理其他任务的时间,避免页面卡顿。

3. 用 ngIf 隐藏父元素是否有用?

如果数据是异步加载的,在数据未完全获取前用 ngIf 隐藏父元素,确实能避免 Angular 进行不必要的变更检测和渲染。但如果数据是一次性同步获取的,这种方式优化效果很有限——Angular 本来就是批量插入 DOM,隐藏父元素只是延迟了渲染时机,并没有减少总的渲染工作量。

示例代码如下:

<div *ngIf="items.length > 0">
  <div *ngFor="let item of items; index as i">
    {{i}} - {{item.title}}
  </div>
</div>
<div *ngIf="items.length === 0">加载中...</div>

内容的提问来源于stack exchange,提问作者tlt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 13:32:14