Infinite scrolling has been around for a while. The basic idea: as you scroll, new content loads at the bottom, creating a seemingly endless scroll. Implementing this is simple, but without careful planning, performance suffers. After a few content refetches, you could have hundreds of DOM elements, many invisible. Luckily, patterns exist to mitigate this, and we'll explore one using Angular.
This is what we want to avoid.
Virtual scrolling renders only a subset of a large list at any time—distinct from infinite scrolling. It's ideal for large datasets where rendering everything at once is inefficient. Only visible (and near-visible) items are rendered; as the user scrolls, items are dynamically swapped. This significantly reduces DOM elements, boosting performance.
Virtual scrolling works by creating a container matching the viewport height. Only the visible items (plus a buffer) are rendered within this container at a specific scroll depth, managed via CSS. Scrolling updates the container, showing new items and removing those out of view, adjusting scroll depth. Combining this with infinite scrolling creates a virtually infinite list without performance penalties.
The example below shows a list of thousands of items, but renders a maximum of 8 at once. Scrolling adjusts the CSS scroll height, creating the illusion of a much longer list.
Let's build an Angular application fetching media from Reddit's paginated API and displaying it in a virtual scrolling list. It will include a search bar for subreddit selection and a filter. Scrolling down loads more content. Our key requirements:
We'll use the @angular/cdk
package (containing the Virtual Scroller component). Install it with npm i @angular/cdk
.
While this example uses Angular, similar patterns are applicable to React, Vue, or vanilla JavaScript. A basic demo illustrating the underlying principles is available here.
First, we create a service to fetch content from the Reddit API using Angular's HttpClient
and RxJS Observables to manage the subreddit name and filter. (Some code is omitted for brevity; the complete implementation is here).
<code class="language-typescript">// ... (Omitted for brevity) ...</code>
The content fetching method tracks specific properties during data requests. A page
property is added to the query string to ensure new content is fetched after the last item. We also filter out NSFW content and items lacking a post hint. This ensures only expected content is displayed.
<code class="language-typescript">// ... (Omitted for brevity) ...</code>
The query$
observable (previously omitted) merges different observable streams before fetching content. The scan
operator combines previous and current stream results, building a large data array across multiple pages.
This allows for extensive scrolling; only subreddit name or filter changes trigger a complete refetch. nextPage
, a property of query$
, stores the last item ID in the current set, used to determine which page to fetch next when nearing the bottom of the Virtual Scroller.
<code class="language-typescript">// ... (Omitted for brevity) ...</code>
The power of RxJS lies in combining and manipulating data streams. This allows us to handle business logic before it reaches the component, keeping the component cleaner and re-usable.
Next, we set up the component to display content using Angular's CdkVirtualScrollViewport
. A method handles scrolling near the viewport bottom, fetching the next page via the subRedditPage$
observable.
<code class="language-typescript">// ... (Omitted for brevity) ...</code>
The template uses the async pipe to subscribe to query$
. Note: Virtual Scrollers become more complex with variable-height content; consistent item heights are recommended for performance.
<code class="language-html">// ... (Omitted for brevity) ...</code>
The onScroll
method fetches more content when the user nears the bottom. It uses the nextPage
ID (from query$
) and emits to subRedditPage$
, triggering the next API call and updating the list via query$
.
<code class="language-typescript">// ... (Omitted for brevity) ...</code>
The search bar and tab controls are also integrated (simplified example below).
<code class="language-typescript">// ... (Omitted for brevity) ...</code>
This creates a virtually infinite scroller. You can test it here. Reddit's API has rate limits; you might hit them during testing. For more details, including additional features, see the GitHub repository here.
The above is the detailed content of Virtually Infinite Scrolling with Angular. For more information, please follow other related articles on the PHP Chinese website!