跳到内容
达斯

通过3种优化方式在Angular中获取大数据

1+

本文重点介绍如何使用Angular优化渲染,这些技术实际上适用于其他框架或仅适用于Vanilla Java脚本。

我们将研究以下技术:

  • 虚拟滚动(使用Angular CDK)
  • 手动渲染
  • 渐进式渲染

虚拟滚动

虚拟滚动可能是处理大型列表的最有效方法。非常感谢 角CDK 和其他插件,在任何组件中都非常容易实现。

这个概念很简单,但是实现并不总是最简单的:

  • 给定一个容器和一个项目列表,则仅当项目’在容器的可见边界内

使用CDK’s滚动模块,我们首先需要安装该模块:

的JavaScript
1
npm i @角度的/光盘

然后,我们导入模块:

的JavaScript
1
2
3
4
5
6
7
进口 { 滚动模块 } '@ 角度的 / 光盘 / 滚动ing';
 
    @Ng模块({
     ...
     进口: [ 滚动模块, ...]
    })
    出口 应用模块 {}

现在,我们可以使用组件在组件中使用虚拟滚动:

的JavaScript
1
2
3
4
5
<光盘-虚拟-滚动-视口 项目Size="50">      
     <div *光盘VirtualFor=“让项目的项目”>
       {{ 项目 }}
     </div>
    </光盘-虚拟-滚动-视口>

如您所见,这非常易于使用,结果令人印象深刻。该组件可以渲染成千上万个项目,而不会出现任何问题。

如果“虚拟滚动”非常好且易于实现,那么为什么还要尝试其他技术呢?这是我的事’我也一直在想— and actually there’原因不止一个原因。

  • 它的方式’s going to work 非常依赖于实现:它’一个单一的实施方案很难管理所有可能的方案。
    例如,我的组件依赖于“自动完成”字段(由同一团队构建),但是不幸的是,它没有’t work as expected. 您的商品越复杂,就越困难’s going to be.
  • 另一个模块,另一个 大量代码添加到您的应用中.
  • 可访问性和可用性:隐藏的项目不会呈现,因此可以赢得’t be searchable.

在许多情况下,虚拟滚动是理想的选择(在可行时):

  • 未定义且可能庞大的项目列表(大约大于5k,但它’高度取决于每个项目的复杂性)
  • 无限滚动项目

手动渲染

我的选择之一’尝试使用Angular手动渲染以加快大量项目的速度’s API,而不是依赖* ngFor。

我们有一个简单的ngFor循环模板:

的JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<TR
        *ngFor=“让数据项; TRackBy:trackById;让isEven =偶数;让isOdd =奇数”
        ="h-12"
        [.bg-灰色-400]=“甚至”
        [.bg-灰色-500]=“ isOdd”
    >
      <d>
        <跨度 =“ py-2 px-4”>{{ 项目.ID }}</跨度>
      </ d>
 
      <td>
        <span>{{ 项目.label }}</s>
      </d>
 
      <d>
        <a>
          <纽扣 =“ py-2 px-4舍入(单击)=”去掉(项目)">x</纽扣>
        </a>
      </d>
    </TR>

I’m使用受启发的基准 js-frameworks-基准 计算10000个简单项目的呈现。

看更多:
Fetch Large Data in 角度的,通过3种优化方式在Angular中获取大数据

第一次基准测试是通过简单的常规* ngFor完成的。结果如下:脚本花费了1099ms,渲染花费了1553ms,绘画花费了3ms。

手动渲染-通过3种优化方式在Angular中获取大数据
手动渲染–通过3种优化方式在Angular中获取大数据

通过使用Angular’的API,我们可以手动呈现项目。

的JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<身体>
      <ng-容器 #项目sContainer></ng-容器>
    </体>
 
    < ng-template #item 让-item =“ 项目” 让-isEven =“ 甚至”>
      <tr 类 =“ h-12”
          [class.bg-gray-400] =“ 甚至”
          [class.bg-gray-500] =“!isEven”
      >
        <td>
          < 跨度 类 =“ py-2 px-4”>{{ 项目.id }}</s>
        </ d>
 
        <td>
          <span>{{ 项目.label }}</s>
        </d>
 
        <d>
          <a>
            <纽扣 =“ py-2 px-4舍入” (点击)=“除去项目)”>x</纽扣>
          </a>
        </d>
      </TR>
    </ng-模板>

控制器’代码的更改方式如下:

  • 我们声明我们的模板和我们的容器

 

的JavaScript
1
2
@ViewChild('itemsContainer', { : ViewContainerRef }) 容器: ViewContainerRef;
    @ViewChild('项目', { : 模板引用 }) 模板: 模板引用<*任何*>;
  • 建立资料时,我们也会使用 ViewContainerRef createEmbeddedView method
的JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
私人的 buildData(长度: ) {
      const 开始 = 这个.数据.长度;
      const 结束 = 开始 + 长度;
 
      对于 ( n = 开始; n <= 结束; n++) {
        这个.容器.createEmbeddedView(这个.模板, {
          项目: {
            ID: n,
            标签: 数学.随机()
          },
          甚至: n % 2 === 0
        });
      }
    }

 

结果显示适度改善:

  • 花费734ms的脚本编写时间,1443渲染和2ms绘画时间
改善效果- 手动渲染-通过3种优化方式在Angular中获取大数据
改善效果– 手动渲染–通过3种优化方式在Angular中获取大数据

但实际上,它’还是超级慢!单击该按钮时,浏览器会冻结几秒钟,从而给用户带来不良的用户体验。

这是它的样子(我’m移动鼠标以模拟加载指示器?):

Fetch Large Data in 角度的,通过3种优化方式在Angular中获取大数据

让’s now TRy 渐进式渲染 combined with 手动渲染.

渐进式渲染

渐进式渲染的概念只是简单地逐步渲染项目的子集,并推迟事件循环中其他项目的渲染。这使浏览器可以平滑且渐进地呈现所有项目。

下面的代码很简单:

  • 我们创建一个间隔,每10ms运行一次,一次渲染500个项目
  • 当所有项目都呈现后,根据索引,我们停止间隔并中断循环
的JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
私人的 buildData(长度: ) {
      const ITEMS_RENDERED_AT_ONCE = 500;
      const INTERVAL_IN_MS = 10;
 
      currentIndex = 0;
 
      const 间隔 = setInterval(() => {
        const nextIndex = currentIndex + ITEMS_RENDERED_AT_ONCE;
 
        对于 ( n = currentIndex; n <= nextIndex ; n++) {
          如果 (n >= 长度) {
            clearInterval(间隔);
            打破;
          }
 
          const 语境 = {
            项目: {
              ID: n,
              标签: 数学.随机()
            },
            甚至: n % 2 === 0
          };
 
          这个.容器.createEmbeddedView(这个.模板, 语境);
        }
 
        currentIndex + = ITEMS_RENDERED_AT_ONCE;
      }, INTERVAL_IN_MS);

请注意,呈现的项目数和间隔时间 完全取决于您的情况。例如,如果您的项目非常复杂,那么一次渲染500个项目肯定会非常缓慢。

正如您在下面看到的,统计数据看起来肯定更糟:

渐进式渲染- 改善效果- 手动渲染-通过3种优化方式在Angular中获取大数据
渐进式渲染– Improvement render – 手动渲染–通过3种优化方式在Angular中获取大数据

什么’虽然用户体验还不错。即使呈现列表所需的时间比以前更长,用户也可以’t tell. We’一次重新渲染500个项目,并且渲染发生在容器边界之外。

发生这种情况时,更改容器的大小或滚动位置可能会引起一些问题,因此在某些情况下需要缓解这些问题。

让’看一下它的样子:

Fetch Large Data in 角度的,通过3种优化方式在Angular中获取大数据

最后的话

上述技术在某些情况下肯定有用,我’当虚拟滚动不是最佳选择时,我们会使用它们。

话虽如此,在大多数情况下,使用像Angular这样的强大库进行虚拟滚动’CDK绝对是解决大型列表的最佳方法。

如果您需要任何澄清,或者您认为不清楚或错误的地方,请发表评论!

1+