Virtual list processing in long list rendering (code attached)

Whether in the real project development or in the interview, the optimization processing method of the front-end is very important. How to render the real long list and thousands of data lists?

First of all, the most common is the front-end and back-end paging. If there are 1000 pieces of data, the front end needs to add the total number of pages and the current number of pages after using ajax to send some necessary data. At this time, if the agreement is 10 pages, then the front end only obtains the 10 pieces of data of the current page. After jumping to different pages, get 10 pieces of data on different pages. This is the simplest processing method, but this method also has its obvious disadvantages. If you want to search for data across pages, you need to open up new storage space for storage. In the actual situation, there are even cases where paging is not possible. How to optimize this?

First, a time slicing method is introduced,

The core idea of time slicing is that if there is a long task that cannot be completed within 50ms (loading and rendering of 100000 data), in order not to block the main thread, the task should give up the control of the main thread so that the browser can handle other tasks. Giving up control means stopping the execution of the current task, letting the browser execute other tasks, and then coming back to continue the unfinished tasks.

//Containers to be inserted
let ul = document.getElementById('container');
// Insert 100000 data
let total = 100000;
// Insert 20 at a time
let once = 20;
//PageCount 
let page = total/once
//Index of each record
let index = 0;
//Cyclic loading data
function loop(curTotal,curIndex){
    if(curTotal <= 0){
        return false;
    }
    //How many articles per page
    let pageCount = Math.min(curTotal , once);
    setTimeout(()=>{
        for(let i = 0; i < pageCount; i++){
            let li = document.createElement('li');
            li.innerText = curIndex + i + ' : ' + ~~(Math.random() * total)
            ul.appendChild(li)
        }
        loop(curTotal - pageCount,curIndex + pageCount)
    },0)
}
loop(total,index);

As shown in the above code, we use setTimeout to load 20 pieces of data at a time. Each setTimeout is a macro task. In the browser's execution mechanism, rendering will be performed after a round of macro tasks is not performed. In this way, rendering can be realized after every 20 pieces of data are loaded, without causing the main thread to be occupied all the time.

The second method is virtual list

The core idea of this method is to get all the data now, but only render the visible part of the window. I don't want to say much. Above

 

 

There are 1000 pieces of data in total, and we only render 10 of them visible at a time. As shown in the figure, 0-9 is displayed. As the scroll wheel moves down, we will render the 10 pieces of data that can be seen on the screen at that time. That is to say, only 10 pieces of data are displayed at the same time, which reduces the dom operation and optimizes the performance.

Let's analyze the code

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css" rel="stylesheet">
    //Analyze css part
        .content{
          background-color: orangered;
          overflow:auto;
          //This is for the roller to appear
          width: 50vw;
          height: 500px;
          //One piece of data is 50px high, and the visual window is 500px. One page can put 10 pieces of data
          margin-left: 25vw;
        }
        .target{
          height: 50000px;
          //The length that the whole pulley can roll, that is, it can store 1000 pieces of data
          box-sizing: border-box;
          //Here, you need to adjust the box model, and then set the offset with the padding top attribute.
        }
    </style>
</head>
<body>
<div class="content" >
    <!-- div The label is a visual window -->
    <ul class ="target">
    <!-- ul The label is the total sliding length -->
    <!-- li The label is placed in it to store the singleton data -->
    </ul>
</div>
</body>

 

<script>
  let datalength = 10;
  //Display data per page
  let data = [];
  //A total of 1000 pieces of data are stored in an array
  let showdata = [];
  //10 pieces of data to be rendered, array storage
  let topdistance = 0;
  //Record offset
  let first;
  //Index of the first data
  let end;
  //Tail bar data index
  for(let i = 0;i<1000;i++){
    data.push(i);
  }
  let div = document.querySelector('.content');
  let ul =  document.querySelector('ul');
  myscroll()
  //First screen rendering data
  div.onscroll =  myscroll
  function myscroll(e){
    ul.innerHTML = '';
    //Empty content before each rendering
    topdistance = e?e.target.scrollTop:0;
    //Manually set offset
    ul.style.paddingTop =  topdistance+'px';
    //Assign the offset to paddingTop. Note that if the above css box model is not set, the roller will slide all the time, and the height of ul will be infinitely elongated
    let index = Math.floor(topdistance/50);
    //Judge where to intercept according to the offset
    first = index;
    end =index+datalength;
    showdata = data.slice(first,end);
    //Intercept native data
    const dom = document.createDocumentFragment();
    let li = null;
    //The dom node is operated to render
    showdata.map((item)=>{ 
       li = document.createElement('li');
       li.style.height = '50px';
       li.innerHTML = item;
       dom.appendChild(li);
    })
    ul.appendChild(dom);
 }
</script>
</html>

Virtual list processing in long list rendering (code attached) - Nuggets

Tags: Javascript Front-end Ajax

Posted by stephenlk on Thu, 18 Aug 2022 16:50:06 +0530