RGJS6 Virtual Scroller
A virtual scroller for the DOM, inspired by virtual-scroller.
Getting started
Install via npm:
npm install rgjs6-virtual-scroller
Usage
See https://unpkg.com/rgjs6-virtual-scroller@latest/jsdoc/index.html
HTML:
<!DOCTYPE html>
<html lang="en">
<body>
<div class="items-container"></div>
</body>
</html>
Javascript:
import VirtualScroller from 'rgjs6-virtual-scroller';
const body = document.body;
const element = document.querySelector('.items-container');
const items = [
{
title: 'Item #1',
subtitle: 'This is the 1st item!',
href: 'https://www.example.com/',
},
// etc...
];
const itemRenderCb = (itemData) => {
const element = document.createElement('a');
a.setAttribute('href', itemData.href);
a.innerHTML = `
<strong>${itemData.title}</strong><br />
${itemData.subtitle}
`;
return a;
};
const scroller = new VirtualScroller(element, items, itemRenderCb, {
viewport: { element: body },
}).init();
Result:
<!DOCTYPE html>
<html lang="en">
<body>
<div class="items-container">
<div data-chunk-index="0">
<a data-item-index="0" href="..."> ... </a>
<a data-item-index="1" href="..."> ... </a>
...
</div>
<div data-chunk-index="1">
<a data-item-index="8" href="..."> ... </a>
<a data-item-index="9" href="..."> ... </a>
...
</div>
</div>
</body>
</html>
Overview
Parameters
Parameter | Type | Default | Description |
---|---|---|---|
element |
HTMLElement | The container element holding the items | |
items |
Array | [] | An array of items |
itemRenderCb |
Function | null | Called for each item that needs to render. Should return an HTMLElement. |
opts |
Object | {} | Options (optional) |
opts.viewport.element |
HTMLElement | undefined | If the container is not the scrolling element, you can provide it here |
opts.viewport.rootMarginMode |
String | 'auto' | Describes how the Viewport.rootMargin value should be interpreted. Allowed values: `'px |
opts.viewport.rootMargin |
Number | 0 | Similar to how IntersectObserver.rootMargin works. The value is added to the offsetTop of a chunk and used to calculate if an item is in the ViewPort |
opts.chunk.itemsPerChunk |
Number | 8 | The number of items a single chunk should contain. |
opts.chunk.keepAlive |
Number | 0 | Determines how long a detached chunk should be kept around before allowing garbage collection. 0 means forever. |
opts.item.intrinsicSize |
Number | 40 | The assumed size of an item until it's rendered, added to DOM and measured. |
opts.item.keepAlive |
Number | 10*1000 | Determines how long a detached item should be kept around before allowing garbage collection. 0 means forever. |
opts.item.cache |
Boolean | true | Enables caching an Item's outerHTML for better performance, trading some memory usage. |
opts.debug |
Boolean | false | Enables debug output in the console. |
Events
Listen for events using the on()
and off()
methods, example:
const scroller = new VirtualScroller( /* ... */ )
scroller.on('chunk-change', () => { /* ... */ })
scroller.init();
Event name | Description |
---|---|
'viewport-resize' |
Fired after the viewport size changed and all components have updated. Details: {viewport: Viewport} . |
'container-resize' |
Fired after the container size changed and all components have updated. Details: {container: Container} . |
'chunk-change' |
Fired after chunks was added or removed and all components have updated. Details: {added: [Chunk, ...], removed: [Chunk, ...]} . |