Giter Site home page Giter Site logo

holmberd / virtual-scroller Goto Github PK

View Code? Open in Web Editor NEW
3.0 2.0 1.0 1.16 MB

A custom web component for efficiently rendering lists with large number of elements.

License: BSD 3-Clause "New" or "Revised" License

JavaScript 100.00%
infinite-scroll list virtual-scroller virtualized virtualized-list virtualized-scroll

virtual-scroller's Introduction

<virtual-scroller>

<virtual-scroller> is a web component that provides a way to render a large number of elements in a scrollable list without negatively affecting overall UI performance. The component achives high performance by only rendering elements that are currently visible in its "viewport" and virtualizes elements not visible outside of it.

The <virtual-scroller> component is technology agnostic allowing you to use it with whichever rendering libary that you are already using in an existing project, e.g. React, lit, Vue...

Performance

<virtual-scroller> has great performance since it takes full advantage of the browser's ability to batch DOM updates which minimizes reflow and repaint. It also has a very small footprint allowing you to keep your bundles small for faster page loads.

Install

The <virtual-scroller> web component can be installed from NPM:

# NPM
npm install @holmberd/virtual-scroller

# Yarn
yarn add @holmberd/virtual-scroller

Example Usage

See react-virtual-scroller for React wrapper.

React

  import VirtualScroller, { Layout, VISIBLE_RANGE_CHANGE_EVENT } from 'virtual-scroller';

  const getItemHeight = (index) => index % 2 === 0 ? 50 : 100;
  const listItems = Array.from(Array(10000).map((index) => ({
    id: index,
    height: getItemHeight(index),
  }));

  function List() {
    const [items, setItems] = useState([]);

    useEffect(() => {
      if (!scrollerRef?.current) {
        return;
      }

      scrollerRef.current.addEventListener(VISIBLE_RANGE_CHANGE_EVENT, ({ detail }) => {
        const { startIndex, stopIndex, offsetIndex } = detail;
        setItems(listItems.slice(startIndex, stopIndex + 1));
      });

      scrollerRef.current.init(listItems.length, getItemHeight, {
        offsetVisibleIndex: 0,
        layout: Layout.VERTICAL,
      });
    }, [])

  return (
    <virtual-scroller style={{ width: 400, height: 400 }} ref={scrollerRef}>
      {items.map(item => <div key={item.id} style={{ height: item.height }}>{item.id}</div>)}
    </virtual-scroller>
  );
}

Methods

init(itemCount: string, getItemLength: function, options: object): void

Once called the virtual-scroller will calculate the visible range and dispatch a visible-range-change event. You can call this multiple times to reset the items scroll index, e.g. to increase item-count when a user scrolls down the list or when the height of an item changes.

Arguments:

  • itemCount: number: The total number of top-level items.
  • getItemLength(index: number): number: Function to calculate and return the length(height or width) of each item by index.

Options:

  • offsetVisibleIndex = 0: Number of extra items to be rendered before/after the visible range.
  • layout = 'vertical': Set whether to use vertical or horizontal layout for virtualization.
  • enableResizeObserver = false: Set wether to update visible item indexes on element resize.
  • disableVirtualization = false: Set to disable virtualization, (visible-range-change will still be dispatched).

resetOnIndex(index: number = 0, shouldUpdate: boolean = true): void

Rebuilds the items cached scrollOffset index on and after the specified index when called. Useful when the size of an item changes in your list, e.g. expanded/collapsed. By default calling this method will trigger an update, use shouldUpdate to override this behaviour.

scrollToItem(index: number): void

Scrolls to the specified item index when called. (The item aligns to the beginning of the list).

Properties

itemCount = 0

Set the total number of top-level items.

getItemLength = (index) => 0

Set function to calculate and return the length(height or width) of each item by index.

offsetVisibleIndex = 0

Set the number of extra items to be rendered before/after the visible range.

enableResizeObserver = false

Set wether to update visible item indexes on element resize.

layout = 'vertical'

Get/Set current layout virtualization mode.

Events

visible-range-change: CustomEvent

Fired when the visible range of item indexes changes.

event.detail.startIndex: number
event.detail.stopIndex: number
event.detail.offsetIndex: number

Browser Support

<virtual-scroller> supports es2020 JavaScript features for desktop and mobile browsers and builds upon standard web platform APIs so that the performance, capabilities and compatibility of the library get better as the web evolves.

Development (TBD)

The following commands are available when developing <virtual-scroller>:

Command Description
npm run build Builds all <virtual-scroller> distributable files.
npm run test Run <virtual-scroller> unit tests.
npm run dev TBD.

Contributing

If you'd like to contribute to <virtual-scroller>, please reach out.

virtual-scroller's People

Contributors

holmberd avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

peerchen

virtual-scroller's Issues

Add TS types

This package could benefit from adding Typescript and types.

Add interactive examples

Code examples are great but it would be good if there were some interactive examples to play with, e.g. scrollable list.

Add horizontal mode RTL support

Add class property to change between LTR and RTL (direction: rtl).

If the element's direction is rtl (right-to-left), then scrollLeft is 0 when the scrollbar is at its rightmost position (at the start of the scrolled content), and then increasingly negative as you scroll towards the end of the content.

Add horizontal virtualization module

The component should support horizontal scrolling, e.g. for horizontal tag scroller. We should therefore add a horizontal-virtualization module similar to the vertical-virtualization module.

  • Add horizontal-virtualization module (see vertical-virtualization.js).
  • Add horizontal-virtualization tests.
  • Add property to the VirtualScroller class to be able to select vertical or horizontal virtualization (not both).
  • Change the VirtualScroller class to switch between vertical and horizontal virtualization calculations.
  • Change the VirtualScroller class variable/method names to better reflect width/height, i.e. size, instead of only height.
  • Add virtual-scroller tests when horizontal virtualization is enabled.

Fix scroll-listener not removed on unmount

this.addEventListener('scroll', this.#handleScroll.bind(this));
if (this.enableResizeObserver) {
this.#connectResizeObserver();
}
if (this.#initialized) {
this.#update();
}
}
disconnectedCallback() {
this.removeEventListener('scroll', this.#handleScroll);
this.#disconnectResizeObserver();
}

removeEventListener on LN275 is not using the bound handler reference at LN264.

Update to store a reference to the scroll event handler and use that to remove the handler on unmount.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.