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>