js实现虚拟表格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>虚拟表格</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }
 
        #list {
            width: 300px;
            height: 500px;
            overflow-y: auto;
            position: relative;
        }
 
        #parent {
            position: relative;
            width: 100%;
        }
 
        #content {
            -webkit-willChange: 'transform';
            willChange: 'transform';
            position: absolute;
            width: 100%;
            left: 0;
            top: 0;
        }
 
        #bg {
            position: absolute;
            z-index: 10;
            width: 100%;
            height: 100%;
            top: 0;
            left: 0;
            background: #fff;
            opacity: 0;
            display: none;
        }
 
        .item {
            min-height: 50px;
            margin-bottom: 5px;
            border: 1px solid #ccc;
            display: flex;
            justify-content: center;
            align-items: center;
        }
    </style>
</head>
 
<body>
    <div id="list">
        <div id="parent">
            <!-- 用来装载内容 -->
            <div id="content"></div>
            <!-- 用来遮挡渲染内容,避免鼠标在不断渲染的content上面的时候导致卡顿无法触发滚动 -->
            <div id="bg"></div>
        </div>
    </div>
 
    <script>
        let itemNum = 100; // 内容总数
        let itemHeight = 52; // 每个内容单元高度
        let list = document.getElementById('list')
        let parent = document.getElementById('parent')
        parent.style.height = `${itemNum*itemHeight}px` // 内容总高度撑开滚动条
        let content = document.getElementById('content')
        let bg = document.getElementById('bg')
 
        let cNum = Math.ceil(list.offsetHeight / itemHeight) // 可视区域个数
        let startIndex = 0 // 可视区域开始index
        let endIndex = startIndex + cNum // 可视区域结束index
 
 
        let data = [...new Array(itemNum).keys()] // 生成所有数据
 
        // 渲染初始数据
        data.slice(startIndex, endIndex).forEach(item => {
            let div = document.createElement('div')
            div.innerHTML = item
            div.setAttribute('class', 'item')
            content.appendChild(div)
        })
 
 
        let timer = null; // 滚动定时器,用于检测是否滚动结束
        let scrollTop = 0; // 当前滚动条高度
        let scrollEndTop = 0; // 停止时滚动条高度
 
 
        function scrollCallBack() {
            clearTimeout(timer);
            timer = setTimeout(isScrollEnd, 500);
            scrollTop = list.scrollTop
            bg.style.display = 'block'
            let sTop = Math.max(list.scrollTop, 0) // 滚动距离,最小取0
            startIndex = Math.floor(sTop / itemHeight) // 可视区域开始index
            endIndex = startIndex + cNum // 可视区域结束index
            content.style.transform = `translateY(${startIndex*itemHeight}px)` // 内容区域偏移
            // 新的数据渲染
            let newData = data.slice(startIndex, endIndex)
            let html = ''
            newData.forEach(item => {
                html += `<div class="item">${item}</div>`
            })
            content.innerHTML = html
        }
 
        // 判断是否滚动结束,将bg遮罩层隐藏
        function isScrollEnd() {
            scrollEndTop = list.scrollTop;
            if (scrollTop === scrollEndTop) {
                console.log('滚动条停止滚动');
                bg.style.display = 'none'
            }
        }
 
        scrollCallBack()
 
        list.addEventListener('scroll', scrollCallBack)
    </script>
</body>
 
</html>

  

posted @   火星_PGY  阅读(163)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示