1、定義監聽函數,監聽onscroll事件
2、提前佔位,並且能獲取每個模塊的高度
3、判斷是否在可視範圍內,如果在,則加載
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
body{
height: 937px;
margin: 0px;
}
</style>
</head>
<body>
<h2 id="title">可視範圍加載</h2>
<div id="main"></div>
<script>
<!-- 模擬模塊 定義高度-->
class module {
setContent(content) {
this.content = content;
}
content;
create() {
return `<div id="content_${this.content}" style="height: ${this.height}px;border: 1px solid red;">${this.content}</div>`
}
height = 500;
getHeight() {
return this.height;
}
}
window.onload = function(){
const moduleArr = [];
const moduleStrArr = [];
for (let i = 0; i < 100; i++) {
const _module = new module(i);
_module.setContent(i);
moduleStrArr.push(_module.create());
moduleArr.push(_module)
}
const div = document.getElementById('main');
div.innerHTML = moduleStrArr.join('');
document.body.appendChild(div);
};
// 滾動
window.onscroll = debounce(()=>{
for (let i = 0; i < 100; i++) {
if (isVisible(document.getElementById('content_'+i))) {
console.log(i);
// 下發處理
}
}
}, 200);
/**
* 防抖 第一次不會立即執行
* @date 2019/12/6
*/
/**
* @desc 函數防抖
* @param fn 函數
* @param timeout 延遲執行毫秒數
* @param immediate true 表立即執行,false 表非立即執行
*/
function debounce(fn, timeout, immediate) {
let _timeout;
return function () {
let context = this;
let args = arguments;
if (_timeout) clearTimeout(_timeout);
if (immediate) {
let callNow = !_timeout;
_timeout = setTimeout(() => {
_timeout = null;
}, timeout);
if (callNow) fn.apply(context, args)
} else {
_timeout = setTimeout(function(){
fn.apply(context, args)
}, timeout);
}
}
}
/**
* @desc 函數節流
* @param fn 函數
* @param timeout 延遲執行毫秒數
* @param type 1 表時間戳版,2 表定時器版
*/
function throttle(fn, timeout ,type) {
let previous = 0;
let _timeout;
return function() {
let context = this;
let args = arguments;
if(type===1){
let now = Date.now();
if (now - previous > timeout) {
fn.apply(context, args);
previous = now;
}
}else if(type===2){
if (!_timeout) {
_timeout = setTimeout(() => {
_timeout = null;
fn.apply(context, args)
}, timeout)
}
}
}
}
/**
* @函數名稱:
* @作用:判斷是否在可視範圍內 目前只處理高度
* @date 2019/12/6
*/
function isVisible(el) {
const _el = el ? getElementPosition(el) : '';
if (_el) {
const windowSize = getWindowSize();
// clientHeight 元素的可視高度,內部滾動,border margin不會計算 padding會計算
// _el.top offsetTop 元素距離上方或者上層控件的位置
// pageYOffset 元素在窗口左上角水平和垂直方向滾動的像素。
// availHeight 窗口的可視高度
// _el.top + el.clientHeight > window.pageYOffset 元素的上偏移值+元素的內部高度>瀏覽器窗口豎直方向滑動值 上面滾入
// window.pageYOffset + windowSize.availHeight> _el.top 瀏覽器窗口豎直方向滑動值+瀏覽器視口高度>元素的上偏移值 下面滾出
return _el.top + el.clientHeight > window.pageYOffset && window.pageYOffset + windowSize.availHeight > _el.top;
}
return false;
}
/**
* @函數名稱:
* @param
* @作用:獲取元素的左邊和上邊的位置
* @date 2019/12/6
*/
function getElementPosition(obj) {
var top = 0;
var left = 0;
while(obj){
top += obj.offsetTop;
left += obj.offsetLeft;
obj = obj.offsetParent;
}
return {top,left};
}
/**
*
* @returns {
* {width: *, height: *, 內容寬高
* availWidth: *, availHeight: 可視寬高
* *, screenHeight: Number, screenWidth: Number 分辨率寬高
* }}
*/
function getWindowSize() {
let xScroll;
let yScroll;
let pageWidth;
let pageHeight;
if (window.innerHeight && window['scrollMaxY']) {
xScroll = window.innerWidth + window['scrollMaxX'];
yScroll = window.innerHeight + window['scrollMaxY'];
} else {
if (document.body.scrollHeight > document.body.offsetHeight) {
// all but Explorer Mac
xScroll = document.body.scrollWidth;
yScroll = document.body.scrollHeight;
} else {
// Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
xScroll = document.body.offsetWidth;
yScroll = document.body.offsetHeight;
}
}
let windowWidth, windowHeight;
if (self.innerHeight) {
// all except Explorer
if (document.documentElement.clientWidth) {
windowWidth = document.documentElement.clientWidth;
} else {
windowWidth = self.innerWidth;
}
windowHeight = self.innerHeight;
} else {
if (document.documentElement && document.documentElement.clientHeight) {
// Explorer 6 Strict Mode
windowWidth = document.documentElement.clientWidth;
windowHeight = document.documentElement.clientHeight;
} else {
if (document.body) {
// other Explorers
windowWidth = document.body.clientWidth;
windowHeight = document.body.clientHeight;
}
}
}
// for small pages with total height less then height of the viewport
if (yScroll < windowHeight) {
pageHeight = windowHeight;
} else {
pageHeight = yScroll;
}
// for small pages with total width less then width of the viewport
if (xScroll < windowWidth) {
pageWidth = xScroll;
} else {
pageWidth = windowWidth;
}
return {
width: pageWidth,
height: pageHeight,
availWidth: windowWidth,
availHeight: windowHeight,
screenHeight: window.screen.height,
screenWidth: window.screen.width,
};
}
</script>
</body>
</html>