这个 scrolling 包为那些要对滚动事件做出反应的指令提供了辅助设施。
cdkScrollable 指令和 ScrollDispatcher 服务一起让组件能对其任意上级滚动容器中的滚动事件做出反应。
要把 cdkScrollable 指令应用在任何充当滚动容器的元素上。这会把该元素标记为 Scrollable 并把它注册到 ScrollDispatcher 中。这时派发器允许组件分享这些事件监听器和应用中所有可滚动容器的知识。
ViewportRuler 是一种可注入的服务,用于衡量浏览器视口的范围。
<cdk-virtual-scroll-viewport> 通过仅仅渲染那些屏幕上可见的条目,来高效的显示大型列表。在任何浏览器中加载数百个元素都会很慢,虚拟滚动可以用一种高效的方式模拟渲染全部条目,方法是让容器元素的高度与要渲染的元素的总高度相同,然后才渲染视图中的条目。虚拟滚动不同于无限滚动这样的策略,它会渲染一定数量的元素,然后在你点击两端时渲染剩下的元素。
*cdkVirtualFor 替换了 <cdk-virtual-scroll-viewport> 中的 *ngFor,它支持与 *ngFor 完全相同的 API。最简单的用法就是指定条目列表(注意,必须在视口中设置 itemSize 属性):
*cdkVirtualFor 让模板中可以使用这些上下文变量:
| 上下文变量 | 描述 |
|---|---|
index |
数据源中条目的索引。 |
count |
数据源中条目的总数。 |
first |
这是否是数据源中的第一个条目。 |
last |
这是否是数据源中的最后一个条目。 |
even |
index 是否为偶数。 |
odd |
index 是否为奇数。 |
所有这些都是本条目在数据源中的索引,而不是在要渲染的那部分数据的索引。
像 *ngFor 的 trackBy 一样,这里也可以指定 trackBy 函数,工作方式也都一样。传给这个 trackBy 的 index 是在数据源中的索引,而不是在要渲染的这部分数据中的索引。
为了提高渲染性能,*cdkVirtualFor 会缓存那些曾经创建过但不再需要的视图。当要创建一个新视图时,会转而复用一个已缓存的视图。可以通过 templateCacheSize 属性来调整视图缓存的大小。把这个大小设置为 0 会禁用缓存。如果你的模板在内存方面很昂贵,你可能会希望减小这个数字,以免在模板缓存上花费太多内存。
*cdkVirtualFor 接受来自 Array、Observable<Array> 或 DataSource 的数据。虚拟滚动的 DataSource 与表格和树组件所用的 DataSource 是同一个。DataSource 只是一个抽象类,它有两个方法:connect 和 disconnect。虚拟滚动视口将调用这个 connect 方法,以接收一个流,这个流会发出要渲染的数据数组。当 viewport 被销毁时,视口会调用 disconnect,这可能是清理连接过程中注册进来的所有订阅的最佳时机。
当所有条目都是固定大小时,你可以使用 FixedSizeVirtualScrollStrategy。可以用 itemSize 指令轻松地将它添加到视口中。这种约束的优点是它可以提供更好的性能,因为在渲染条目时不需要进行测量。
固定大小的策略也支持设置一些缓冲区参数,用来决定渲染多少额外内容,也就是视口可见内容之外的部分。第一个参数是 minBufferPx。minBufferPx 是视口必须渲染的最小内容缓冲区数量(以像素为单位)。如果视口检测到要缓冲的内容小于这个数量(未填满),就会立即渲染更多内容。第二个参数是 maxBufferPx。它会告诉视口当检测到需要更多缓冲区的时候要渲染多少个备用缓冲区空间。
这两个缓冲区参数的作用可以用一个例子来说明。假设我们有以下参数:itemSize = 50、minBufferPx = 100、maxBufferPx = 250。当用户滚动浏览内容时,视口就会检测到只剩下 90px 的缓冲区。由于它小于 minBufferPx,所以视口必须渲染更多缓冲区。它必须渲染足够数量的缓冲区,直到其大于等于 maxBufferPx。在这种情况下,它渲染了 4 个条目(额外的 200px),使缓冲区总大小达到 290px,略高于 maxBufferPx。
其他虚拟滚动策略可以通过扩展 VirtualScrollStrategy 来实现。目前正在 @angular/cdk-experimental 开发一种适用于不同大小元素的自动调整策略,但还没有准备好用于生产环境。
虚拟滚动视口默认为垂直方向,也可以设置为 orientation="horizontal"。在改变方向时,要确保该条目是用 CSS 进行水平布局的。要做到这一点,你可能希望把 .cdk-virtual-scroll-content-wrapper 类作为 CSS 的目标,它是包含待渲染内容的包装元素。
某些 HTML 元素(如 <tr> 和 <li>)对它们所在的父元素种类有一些限制。要想对这些类型的元素进行虚拟滚动操作,就要把它们放在合适的父元素中,然后把它们共同包装在 cdk-virtual-scroll-viewport 中。注意,父组件中不要引入额外的空白区(比如通过 margin 或 padding),因为这样会干扰滚动。
为了确定整个内容的大小以及它在任何时刻需要实际渲染的内容,视口依赖于所提供的一个 VirtualScrollStrategy。提供它的最简单方式是在视口上使用 itemSize 指令(例如 <cdk-virtual-scroll-viewport itemSize="50">)。但是,也可以通过创建一个实现 VirtualScrollStrategy 接口的类来提供自定义策略,并在包含此视口的组件上把它提供为 VIRTUAL_SCROLL_STRATEGY。
渲染非平凡条目的虚拟滚动视口可能会发现,在用户滚动时简单地附加到列表而用不删除已渲染的视图会更高效。 appendOnly 输入确保已渲染的视图在滚动出视图后仍保留在 DOM 中。
默认情况下,虚拟滚动视口本身就会充当滚动元素。但是,在某些情况下,你可能希望让此视口滚动其父元素之一。例如,如果你想要一些非虚拟化内容,用户可以在虚拟化内容之前或之后滚动浏览。
要将 cdk-vritual-scroll-viewport 配置为使用其父元素之一作为滚动元素,请把 cdkVirtualScrollingElement 应用于那个父元素。
另一种常见的情况是使用窗口本身作为滚动元素。这在移动设备上通常是更好的用户体验,因为它允许浏览器 chrome 滚动消失。要使用窗口作为滚动元素,请将
scrollWindow 属性添加到
cdk-virtual-scroll-viewport。