1、js
<body>
test
<div id="content"></div>
<script>
let arr = []
for(let i= 1; i < 1001; i++) {
let item = {}
item.title = '标题' + i
item.content = '内容'
arr.push(item)
}
loadAll(arr);
function loadAll(response) {
//将10万条数据分组, 每组500条,一共200组
var groups = group(response);
console.log('groups:', groups); // [{},{},...]
for (var i = 0; i < groups.length; i++) {
//闭包, 保持i值的正确性
window.setTimeout(function () {
var group = groups[i];
var index = i + 1;
return function () {
//分批渲染
loadPart( group, index );
}
}(), 1);
}
}
//数据分组函数(每组500条)
function group(data) {
var result = [];
var groupItem;
for (var i = 0; i < data.length; i++) {
if (i % 500 == 0) {
groupItem != null && result.push(groupItem);
groupItem = [];
}
groupItem.push(data[i]);
}
result.push(groupItem);
return result;
}
var currIndex = 0;
//加载某一批数据的函数
function loadPart( group, index ) {
var html = "";
for (var i = 0; i < group.length; i++) {
var item = group[i];
// html += "<li>title:" + item.title + index + " content:" + item.content + index + "</li>";
html += item.title + item.content + "";
}
console.log('index:', index);
//保证顺序不错乱
console.log('index - currIndex:', index - currIndex);
while (index - currIndex == 1) {
// $("#content").append(html);
document.getElementById("content").append(html);
currIndex = index;
console.log('currIndex:', currIndex);
}
}
</script>
</body>
2、vue
父
<template>
<div id="app">
<VirtualList :listData="data" :itemSize="100"/>
</div>
</template>
<script>
import VirtualList from "./components/VirtualList";
let d = [];
for (let i = 0; i < 1000; i++) {
d.push({ id: i, value: i });
}
export default {
name: "App",
data() {
return {
data: d
};
},
components: {
VirtualList
}
};
</script>
<style>
html{
height: 100%;
}
body{
height: 100%;
margin:0;
}
#app{
height:100%;
}
</style>
子组件
<template>
<div ref="list" class="infinite-list-container" @scroll="scrollEvent($event)">
<div class="infinite-list-phantom" :style="{ height: listHeight + 'px' }"></div>
<div class="infinite-list" :style="{ transform: getTransform }">
<div ref="items"
class="infinite-list-item"
v-for="item in visibleData"
:key="item.id"
:style="{ height: itemSize + 'px',lineHeight: itemSize + 'px' }"
>{{ item.value }}</div>
</div>
</div>
</template>
<script>
export default {
name:'VirtualList',
props: {
//所有列表数据
listData:{
type:Array,
default:()=>[]
},
//每项高度
itemSize: {
type: Number,
default:200
}
},
computed:{
//列表总高度
listHeight(){
return this.listData.length * this.itemSize;
},
//可显示的列表项数
visibleCount(){
return Math.ceil(this.screenHeight / this.itemSize)
},
//偏移量对应的style
getTransform(){
return `translate3d(0,${this.startOffset}px,0)`;
},
//获取真实显示列表数据
visibleData(){
return this.listData.slice(this.start, Math.min(this.end,this.listData.length));
}
},
mounted() {
this.screenHeight = this.$el.clientHeight;
this.start = 0;
this.end = this.start + this.visibleCount;
},
data() {
return {
//可视区域高度
screenHeight:0,
//偏移量
startOffset:0,
//起始索引
start:0,
//结束索引
end:null,
};
},
methods: {
scrollEvent() {
//当前滚动位置
let scrollTop = this.$refs.list.scrollTop;
//此时的开始索引
this.start = Math.floor(scrollTop / this.itemSize);
//此时的结束索引
this.end = this.start + this.visibleCount;
//此时的偏移量
this.startOffset = scrollTop - (scrollTop % this.itemSize);
}
}
};
</script>
<style scoped>
.infinite-list-container {
height: 100%;
overflow: auto;
position: relative;
-webkit-overflow-scrolling: touch;
}
.infinite-list-phantom {
position: absolute;
left: 0;
top: 0;
right: 0;
z-index: -1;
}
.infinite-list {
left: 0;
right: 0;
top: 0;
position: absolute;
text-align: center;
}
.infinite-list-item {
padding: 10px;
color: #555;
box-sizing: border-box;
border-bottom: 1px solid #999;
}
</style>
from: 掘金 云中桥
CodeSandbox 是一个在线的代码编辑器,主要聚焦于创建 Web 应用项目。
支持主流的前端相关文件的编辑:JavaScript、TypeScript、CSS、Less、Sass、Scss、HTML、PNG 等。支持自动代码提示。