实现图片懒加载(throttle, debounce)

1,491 阅读2分钟

很早之前就想去实现一些功能,最近时间比较多就试试,本人是菜鸟- -大佬轻点

懒加载

/**
 * 图片懒加载
 * @parma imgItems {node[]} DOM节点
 * @returns {boolean} 可改进为promise方法
 */
function lazyLoad(imgItems) {
    let _fnScrollTop =  window.scrollY;
    /**
     * @parma arr {node[]}  
     * @parma item {node}
     */
    function delItem(arr, item) {
    	if(arr.indexOf(item) != -1) {
    		item.setAttribute('src',item.dataset.src)
    		// arr.indexOf(item)寻找对应位置
    		arr.splice(arr.indexOf(item), 1)
    	}
    }
    imgItems.forEach((item, index, arr) => {
    	// 获取img的底部高度
    	let itemClientY = item.offsetTop +item.offsetHeight;
    	// 判断img高度(底部)是否在屏幕中
    	if(item.offsetTop < window.innerHeight + _fnScrollTop && item.offsetTop > _fnScrollTop) {
    		delItem(arr, item)
    	} else if (itemClientY < window.innerHeight + _fnScrollTop && itemClientY > _fnScrollTop)  {
    		delItem(arr, item)
    		
    	}
    })
}
防止传入的参数非数组
function lazyLoad(imgItems) {
    ...
    if(imgItems.length === 0) {
    	return true
    }
    ...
}
全部图片加载完成后return
function lazyLoad(imgItems) {
    ...
    if(!Array.isArray(imgItems)) {
    	return false
    }
    ...
}

imgItems其中arr.splice(arr.indexOf(item), 1)删除对应的item

使用
// html
<ul>
    <li><img src="img/10.gif" data-src="img/1.jpg"></li>
    <li><img src="img/10.gif" data-src="img/2.jpg"></li>
    <li><img src="img/10.gif" data-src="img/3.jpg"></li>
    <li><img src="img/10.gif" data-src="img/4.jpg"></li>
    <li><img src="img/10.gif" data-src="img/5.jpg"></li>
    <li><img src="img/10.gif" data-src="img/6.jpg"></li>
    <li><img src="img/10.gif" data-src="img/7.jpg"></li>
</ul>
// js
let imgNodes = [...document.querySelectorAll('img')];
lazyLoad(imgNodes);

debounce

去抖的概念的意思是如电梯一样,当你重复按的时候,总是以最后一下为计时的开始

/**
 * 去抖
 * @parma fn {function} 执行的方法
 * @parma delay {nubmer} 去抖的时间
 * @parma args {any | object} fn的参数
 */
function debounce(fn = function(){}, delay, args) {
    let timer;
    return () => {
        if(timer) {
            clearTimeout(timer)
        }
        timer = setTimeout(() => {
            fn(args);
    	}, delay)
    }
}

throttle

节流的概念: 计时开始后过程中你重复按都没用

/**
 * 节流
 * @parma fn {function} 执行的方法
 * @parma delay {nubmer} 节流的时间
 * @parma args {any | object} fn的参数
 */
function throttle(fn = function(){}, delay, args) {
    let times = true;
    return () => {
    	if(times) {
            setTimeout(() => {
            	fn(args);
            	times = true;
            }, delay)
    	}
    	times = false;
    }
}
使用
<ul>
    <li><img src="img/10.gif" data-src="img/1.jpg"></li>
    <li><img src="img/10.gif" data-src="img/2.jpg"></li>
    <li><img src="img/10.gif" data-src="img/3.jpg"></li>
    <li><img src="img/10.gif" data-src="img/4.jpg"></li>
    <li><img src="img/10.gif" data-src="img/5.jpg"></li>
    <li><img src="img/10.gif" data-src="img/6.jpg"></li>
    <li><img src="img/10.gif" data-src="img/7.jpg"></li>
</ul>
<script>
    let imgNodes = [...document.querySelectorAll('img')];
    lazyLoad(imgNodes)
    // debounce
    window.addEventListener('scroll', debounce(lazyLoad, 100, imgNodes))
    // throttle
    window.addEventListener('scroll', throttle(lazyLoad, 100, imgNodes))
</script>