A long list of front-end business encounters

Front-end business development will encounter some large data can not be paginated to load the list, we often call it a long list. Since it is a long list, rendering the entire list the first time is not allowed by business: it is too long. Second, the performance is also very low.

Long list solutions

  • Lazy loading: This is the usual infinite scrolling, rendering one part at a time, and as you scroll, the rest of the rendering appears in the visual area.
  • Visible area (also known as virtual list) : a fixed window with a scroll bar on the right. Fixed window height is the viewable area.

Q: What’s the difference between virtual lists and wireless scrolling?

Infinite scroll is generally common bottom loading, scroll to the bottom of the page to load more data, when the amount of data, but, after tens number level, the browser can’t carry so many node rendering, will certainly be caton collapse, even this time you can use the virtual list, by calculating the rolling window, rendering visible part of the screen each time node, Using padding outside of the screen instead of being invisible, the browser renders the nodes within the screen no matter where you scroll, so there’s no performance burden.

Example: Performance analysis after 10,000 li data are inserted.

document.getElementById('button').addEventListener('click'.function(){
    // Record the start time of the task
    let now = Date.now();
    const total = 10000;
    let ul = document.getElementById('container');
    // Insert the data into the container
    for (let i = 0; i < total; i++) {
        let li = document.createElement('li');
        li.innerText = ~~(Math.random() * total)
        ul.appendChild(li);
    }
    console.log('JS runtime: '.Date.now() - now);
    setTimeout(() = >{
      console.log('Total elapsed time:'.Date.now() - now);
    },0)

    // print JS runtime: 38
    // print total runtime: 957
  })
Copy the code

Event(Click) : 40.84ms Recalculate Style: 105.08 MS Layout: 731.56 MS Update Layer Tree: 58.87ms Paint: 15.32msCopy the code

Some students may have a question: why can you say that the card node JS runtime and total runtime

The event loop of the browser

  • The execution stack managed by the JS engine is emptied and all microtask events are completed, triggering the rendering thread to render the page.
  • The second console.log(), trigger time: executed in the next Event Loop after rendering is complete.

As you can see, recalculate Style and layout take the most time

Solution:

  1. The best way to optimize a long list is to use a few ready-made virtualized list components, the most common ones are Act-Virtualized and Act-Tiny-Virtual-List. Then you can effectively optimize your long list by using them.

  2. A freestanding implementation

Preliminary knowledge:

High page visible area: the document. The body. High clientHeight web page text full text: document. Body. ScrollHeight web high visible area (including the high line) : Document. Body. OffsetHeight web swept to high: the document. The body. The scrollTop high screen resolution: window. The screen. The heightCopy the code
<! DOCTYPE html><html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
  <title>Simple implementation of virtual lists</title>
</head>
<style>
  .list-view {
    height: 400px;
    overflow: auto;
    position: relative;
    border: 1px solid #aaa;
  }

  .list-view-phantom {
    /* Using the invisible area, prop up the list so that the list scroll bar appears */
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    z-index: -1;
  }

  .list-view-content {
    left: 0;
    right: 0;
    top: 0;
    position: absolute;
  }

  .list-view-item {
    padding: 5px;
    color: # 666;
    line-height: 30px;
    box-sizing: border-box;
  }

  [v-cloak] {
    display: none;
  }
</style>

<body>
  <div id="app" v-cloak>
    <div class="list-view" ref="scrollBox" @scroll="handleScroll">
      <div class="list-view-phantom" :style="{ height: contentHeight }"></div>
      <div ref="content" class="list-view-content">
        <div class="list-view-item" :style="{ height: itemHeight + 'px' }" v-for="item in visibleData">
          {{ item }}
        </div>
      </div>
    </div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    new Vue({
      el: "#app".computed: {
        contentHeight() {
          return this.data.length * this.itemHeight + "px"; }},mounted() {
        this.updateVisibleData();
      },
      data() {
        return {
          data: new Array(100).fill(1),
          itemHeight: 30.visibleData: [],}; },methods: {
        updateVisibleData(scrollTop = 0) {
          console.log('scrollTop', scrollTop)
          const visibleCount = Math.ceil(
            this.$refs.scrollBox.clientHeight / this.itemHeight
          );
          const start = Math.floor(scrollTop / this.itemHeight);
          const end = start + visibleCount;
          this.visibleData = this.data.slice(start, end);
          this.$refs.content.style.webkitTransform = `translate3d(0, ${start * this.itemHeight
            }px, 0)`;
        },
        handleScroll() {
          const scrollTop = this.$refs.scrollBox.scrollTop;
          this.updateVisibleData(scrollTop); ,}}});</script>
</body>

</html>

Copy the code

To be perfect

  • Dynamic list
  • List of listeners with images, using the experimental API ResizeObserver