實現圖片懶載入(throttle, debounce)

hackLi發表於2019-03-21

很早之前就大叔實現一些功能,最近時間比較多就試試,本人是菜鳥- -大佬輕點

懶載入

/**
 * 圖片懶載入
 * @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>
複製程式碼

相關文章