前端虚拟列表(长列表优化)

使用场景及原理:

场景:接口一次性返回所有数据,数据量特别庞大,会导致页面DOM元素过多,页面就会变得很卡,此时可以使用虚拟列表来解决

原理:只在可视区域内展示数据

css部分:

.box {
    width: 500px;
    height: 800px;
    position: relative;
    box-sizing: border-box;
    overflow-y: scroll;
    background-color: blanchedalmond;
}

.list {
    box-sizing: border-box;
}

.item {
    height: 30px;
    text-align: center;
    line-height: 30px;
    color: #000;
    background-color: cadetblue;
}

html部分:

js部分:

// 数据
let list = []
for (let i = 0; i < 100000; i++) {
    list.push(i + 1)
}

// dom部分
const BOX = document.getElementById('box'),
     LIST = document.getElementById('list'),
     NUM = Math.floor(BOX.clientHeight / 30) + 2

// 开始结束索引(渲染这个索引区域的数据)
let startIndex = 0,
    endIndex = NUM

LIST.style.height = list.length * 30 + 'px' // 设置列表高度
setData(startIndex, endIndex) // 渲染初始数据
BOX.addEventListener('scroll', e => handleBoxScroll(e)) // 添加滚动事件

function handleBoxScroll(e) {
    startIndex = Math.floor(e.target.scrollTop / 30) // 开始索引 = 滚动距离 / 每一项的高度
    endIndex = NUM + startIndex // 结束索引 = 初始结束索引 + 新的开始索引
    setBoxPadding(startIndex) // 设置列表paddingTop
    setData(startIndex, endIndex) // 渲染数据
}

// 设置可视区域数据
function setData(startIndex, endIndex) {
    let fragment = document.createDocumentFragment() // 创建文档碎片
    let showList = list.slice(startIndex, endIndex) // 取出要渲染的数据
    for (let i = 0; i < showList.length; i++) { // 循环添加节点
        let el = document.createElement('div')
        el.className = 'item'
        el.innerText = `列表项${showList[i]}`
        fragment.appendChild(el)
    }
    LIST.innerHTML = '' // 清空子节点
    LIST.appendChild(fragment) // 一次性渲染到视图上
}

// 设置容器内边距
function setBoxPadding(start) {
    LIST.style.paddingTop = start * 30 + 'px'
}

以上就是本文所有内容,第一次写文章,有不对的地方欢迎大家提出,非常感谢!!!

你可能感兴趣的:(优化,前端,javascript,vue.js)