Recently, ticketing items have returned too much data at one time, my computer can still hold, but when I see the customer’s computer suddenly exploded… It’s not like we’re going to look at tabular data optimization again

1. Problem summary

  • The back end returns too much data at once and renders directly causing performance lag
  • The dom rendering of large amounts of data on a lesser computer tends to freeze
  • How do you optimize lists when function throttling and anti-shaking optimizations basically don’t work

2. Virtual scroll icon

In fact, it is listening to the scroll event to continuously update the existing list of data, as shown in the following figure:

If you look at the console, the number of divs in the list doesn’t change, it just changes the data inside it.

Graphic implementation logic: can be understood as a virtual scroll is three outer box for Windows, an intermediary for the height of the whole data list box just do not render any data open height and the effect of rolling, the inner box rendering and display data and inner scroll box constantly replace data and simulated rolling effect;

3. Code implementation

Points vUE and native JS for implementation can be used directly copy

vue
<template>
    <div :style="`height:${viewH}px; overflow-y:scroll`" @scroll="handleScroll" class="out">
        <div :style="`height:${scrollH}px`" class="list">
            <div class="item_box" :style="`transform:translateY(${offsetY}px)`">
                <div class="item"
                     :style="`height: ${itemH}px`"
                     v-for="(item, index) of list"
                     :key="index">
                    {{ item }}
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: "virtualList".props: {
            data: Array.// List total data
            viewH: Number.// External height
            itemH: Number.// Single height
        },
        data() {
            return {
                scrollH: ' '.// The entire scrolling list height
                list: [].// The data is displayed each time
                showNum: ' '.offsetY: ' '.// Dynamic offset - the outer box is set to scroll
                lastTime: ' ',}},mounted() {
            // Initialize the calculation
            this.scrollH = this.data.length * this.itemH;
            // Calculate the visualization height can be loaded several lists at a time, set several more to prevent direct replacement during scrolling
            this.showNum = Math.floor(this.viewH / this.itemH) + 4;
            // Display several by default
            this.list = this.data.slice(0.this.showNum);
            this.lastTime = new Date().getTime();
        },
        methods: {
            handleScroll(e) {
                if (new Date().getTime() - this.lastTime > 10) {
                    let scrollTop = e.target.scrollTop; // The width of the scroll bar
                    // After each scroll, the scrollTop value gets an offset that is divisible by itemH
                    ScrllTop = 1220 1220% this.itemH = 20 offsetY = 1200
                    this.offsetY = scrollTop - (scrollTop % this.itemH);
                    console.log(scrollTop, scrollTop % this.itemH);
                    this.list = this.data.slice(
                        Math.floor(scrollTop / this.itemH),  // Count how many entries are involved
                        Math.floor(scrollTop / this.itemH) + this.showNum
                    )
                    this.lastTime = new Date().getTime(); }}}}</script>
Copy the code
/ / class<! DOCTYPE html><html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #list {
            border: 1px solid # 333333;;
            overflow-y: scroll;
        }

        .listBox {
            border: 1px solid #00B7FF;
        }
    </style>
</head>
<body>
<div id="list"></div>
</body>
<script>
    /* * Configuration items: * el: hook * data: all list items * viewH: list height * itemH: height of each item * list: current display items * * * showNum: number of display items * * */
    class List {
        constructor(opt) {
            this.el = opt.el;
            this.data = opt.data;
            this.viewH = opt.viewH;
            this.itemH = opt.itemH;
            this.totalH = this.data.length * this.itemH + 'px';
            this.list = [];
            this.offsetY = 0;
            this.showNum = 0;
            this.lastTime = new Date().getTime();

            this.el.style.height = this.viewH + 'px';
        }

        init() {
            this.composeDom();
            this.initData();
            this.bindEvent();
        }

        composeDom() {
            // Create a DOM structure
            let totalBox = document.createElement('div'),
                listBox = document.createElement('div');
            totalBox.className = 'totalBox';
            totalBox.style.height = this.totalH;
            listBox.className = 'listBox';
            totalBox.append(listBox);
            this.el.append(totalBox);
            this.totalBox = totalBox;
            this.listBox = listBox;
        }

        initData() {
            // Initialize the list
            this.showNum = Math.floor(this.viewH / this.itemH) + 4;
            this.list = this.data.slice(0.this.showNum);
            this.createByList(this.list);

        }

        createByList(list) {
            this.listBox.innerText = ' ';
            let fragment = document.createDocumentFragment();
            for (let i = 0; i < this.showNum; i++) {
                let div = document.createElement('div');
                div.style.height = this.itemH + 'px';
                div.innerText = list[i];
                fragment.append(div);
            }
            this.listBox.append(fragment);
        }

        bindEvent() {
            this.el.addEventListener('scroll'.this.handleScroll.bind(this), false);
        }

        handleScroll(e) {
            if (new Date().getTime() - this.lastTime > 20) {
                let scrollTop = e.target.scrollTop,
                    prevNum = Math.floor(scrollTop / this.itemH);
                this.offsetY = scrollTop - (scrollTop % this.itemH);
                this.list = this.data.slice(prevNum, prevNum + this.showNum);
                this.createByList(this.list);
                this.listBox.style.transform = `translateY(The ${this.offsetY}px)`
                this.lastTime = new Date().getTime(); }}}let data = [];
    for (let i = 0; i < 999; i++) {
        data.push(i + 1);
    }


// The instance is mounted
    new List({
        el: document.getElementById('list'),
        data,
        viewH: 600.itemH: 40
    }).init();
</script>
</html>
Copy the code

4. Summarize the knowledge

It is the use of scrollTop, how to calculate how many pieces of data have been involved according to the height of involvement, to show the subsequent data. Well actually very simple, but also study an afternoon ah, now still working overtime, have nothing to do to write out the problems encountered today, I hope to help you. ヾ(◍°∇°◍) Blue