Virtual list: In short, for a large number of list data, only part of the data source corresponding to the visible area within the scroll area is rendered

Here’s an example:

For example, if I want to render 1000 pieces of data, and each piece of data is 60px high, if I want to render all the elements, then the scroll area needs to be at least 6000px high. However, if I render 1000 pieces of data, then the whole DOM tree will have a huge number of DOM elements. Once reflow redraw can be very slow.

This scenario is to take the optimized plan for the virtual list to apply colours to a drawing, that we have to do is only render when rolling viewing area corresponding dom elements, namely below B, not to render the non-visual area elements (C, D area does not render elements), so can reduce a large number of unnecessary dom rendering (C, D areas users don’t need to see, So its DOM rendering is not necessary) to improve performance!

Virtual list implementation principle: According to the viewport height (B area height in the figure above), the scrolling distance of the parent element (scrollTop) and the average height of each list element item, calculate the part of data to be displayed in the list of data sources corresponding to the viewport height from the current scrollTop to scrollTop+ viewport height. For hidden scroll area C,D fills it with paddingTop&&paddingBottom, keeping the height of the whole scroll area unchanged and monitoring scroll at the same time. PaddingTop &paddingBottom dynamically changes area data when scrolling triggers:

  • 1. Listen for container elements to scroll

  • 2. Get the scrollTop distance of container elements

  • StartIndex = scrollTop/itemHeight

  • 4. Obtain endIndex (in data source) of the last element to be rendered in the visible area under the current scrollTop. EndIndex = startIndex + viewHeight (viewHeight)/itemHeight (itemHeight)

  • ViewData =dataSource (dataSource). Slice (startIndex,endIndex+1)

  • PaddingTop = startIndex*itemHeight paddingTop = startIndex*itemHeight

  • 7, Calculate the height of area D (paddingBottom) -paddingTop- View area height (viewHeight)

  • 8, clear the last data in the region, refill it with the new data viewData, and set the new paddingTop&paddingBottom

Code implementation

<! DOCTYPEhtml>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        html.body {
            width: 100%;
            height: 100%;
            margin: 0;
        }

        #container {
            width: 100%;
            height: 100%;
        }

        #content {
            background-color: pink;
        }
    </style>
</head>

<body>
    <div id="container">
        <div id="content"></div>
    </div>
    <script>

        function createVlist(container, content, data_Source, item_Height) {
            const dataSource = data_Source  / / the data source
            const itemHeight = item_Height  // The height of each row
            const viewHeight = container.clientHeight // Viewport height (part of the height shown in the virtual list)
            const contentHeight = itemHeight * dataSource.length // The height of the scroll area
            const itemCount = Math.ceil(viewHeight / itemHeight) // Number of viewport elements
            // Set overflow: auto (generates a scroll area, not intercepted)
            container.setAttribute('style'.`overflow:auto`)
            // Set the height of the scroll area
            content.setAttribute('style'.`height:${contentHeight}px`)
            const scrollCallback = e= > {
                const scrollTop = e.target.scrollTop                 // The scrolling distance of the container element
                const startIndex = Math.ceil(scrollTop / itemHeight) // The index of the data source where the first element of the viewport resides
                const endIndex = startIndex + itemCount              // The index of the data source where the last element of the viewport resides
                // Use startIndex endIndex to find the part of the data source that needs to be displayed in the virtual list
                const itemList = dataSource.slice(startIndex, endIndex + 1)

                // Scrolling area Height contentHeight = Scrolling area paddingTop + Viewport height + Scrolling area paddingBottom
                const paddingTop = startIndex * itemHeight
                const paddingBottom = contentHeight - paddingTop - itemCount * itemHeight

                PaddingTop paddingBottom dynamically adjusts the scroll area to ensure that the list section is always displayed in the viewport
                content.setAttribute('style'.`padding-top:${paddingTop}px; padding-bottom:${paddingBottom}px`)
                Delete the last batch list data before displaying the next batch list
                content.innerHTML = ' '
                // Dynamically adjust the corresponding display data after each scroll
                for (const val of itemList) {
                    const item = document.createElement('div')
                    item.innerHTML = val
                    item.setAttribute('style'.`background-color:${val % 2= = =0 ? 'red' : 'blue'}; width:100%; height:${item_Height}px`)
                    content.appendChild(item)
                }
            }
            // Add a scrolllistener for container elements
            container.addEventListener('scroll', scrollCallback)
            // Initial first screen data
            scrollCallback({ target: container })
        }
        // Create a virtual list
        createVlist(container, content, Array.from({ length: 100 }, (v, i) = > i), 60)

    </script>
</body>

</html>
Copy the code