可运行的例子
<style>
* {
margin: 0;
padding: 0;
}
#wrapper {
margin: 100px auto;
width: 300px;
height: 300px;
border: 1px solid rgba(100, 100, 100, 0.2);
overflow-y: scroll;
}
ul#container {
list-style: none;
padding: 0;
width: 100%;
}
ul#container > li {
height: 30px;
width: 100%;
}
ul#container > li.green-item {
background-color: #c5e3ff;
}
ul#container > li.red-item {
background-color: #fff5d5;
}
</style>
<body>
<div id="wrapper" onscroll="handleScroll()">
<ul id="container"></ul>
</div>
</body>
<script>
// 模拟数据构造
const arr = [];
const nameArr = ['Alice', 'July', 'Roman', 'David', 'Sara', 'Lisa', 'Mike'];
let curPage = 1;
let noData = false;
const curPageSize = 20;
const getPageData = (page, pageSize) => {
if (page > 5) return [];
const arr = [];
// const nameArr = ['Alice', 'July', 'Roman', 'David', 'Sara', 'Lisa', 'Mike'];
for (let i = 0; i < pageSize; i++) {
arr.push({
number: i + (page - 1) * pageSize,
name: `${nameArr[i % nameArr.length]}`,
});
}
return arr;
};
const wrapper = document.getElementById('wrapper');
const container = document.getElementById('container');
let plainWrapper = null;
/**
* @method handleScroll
* @description: 滚动事件监听
*/
const handleScroll = () => {
// 当临界元素进入可视范围时,加载下一页数据
if (
!noData &&
container.clientHeight - wrapper.scrollTop <= wrapper.clientHeight
) {
curPage++;
console.log(curPage);
const newData = getPageData(curPage, curPageSize);
renderList(newData);
}
};
/**
* @description: 列表渲染
* @param {Array} data
*/
const renderList = (data) => {
// 没有更多数据时
if (!data.length) {
noData = true;
plainWrapper.innerText = 'no more data...';
return;
}
plainWrapper && container.removeChild(plainWrapper); //移除上一个临界元素
const fragment = document.createDocumentFragment();
data.forEach((item) => {
const li = document.createElement('li');
li.className = item.number % 2 === 0 ? 'green-item' : 'red-item'; //奇偶行元素不同色
const text = document.createTextNode(
`${`${item.number}`.padStart(7, '0')}-${item.name}`
);
li.appendChild(text);
fragment.appendChild(li);
});
const plainNode = document.createElement('li');
const text = document.createTextNode('scroll to load more...');
plainNode.appendChild(text);
plainWrapper = plainNode;
fragment.appendChild(plainNode); //添加新的临界元素
container.appendChild(fragment);
};
// 初始渲染
renderList(getPageData(curPage, curPageSize));
</script>
考虑的文章来源
www.jb51.net/article/278…
再说到webworker的技术 建立 work.js文件
onmessage
postmessage
teminate
//也可以开启多个work,放到一个线程池中
self.onmessage = function(event) {
const messageFromMain = event.data;
const result = doSomeHeavyCalculations(messageFromMain);
self.postMessage(result);
};
function doSomeHeavyCalculations(message) {
// 模拟一些耗时的计算
let sum = 0;
for (let i = 0; i < 2000; i++) {
for (let i = 0; i < 100; i++) {
sum += Math.random()
}
}
return 'Result: ' + (sum + message);
}
再button响应相关的事件
const startWorkerButton = document.getElementById('startWorker');
const resultElement = document.getElementById('result');
startWorkerButton.addEventListener('click', () => {
const worker = new Worker('work.js');
worker.onmessage = function(event) {
resultElement.textContent = 'Result from Web Worker: ' + event.data;
worker.terminate() //来销毁这个woker
};
worker.postMessage('Hello from main thread!');
});
看一个浏览器是否支持work: typeof Worker=='function'