scroll實現
上次我們聊到的是throttle和debounce去實現 實現圖片懶載入(throttle, debounce)
不過,就算throttle和debounce是實現圖片懶載入,但是scroll事件密集發生,計算量很大,容易造成效能問題。
IntersectionObserver
這api主要負責監聽元素和"視口"(viewport)的關係,我就不多講述了
- API
Intersection Observer - Web API 介面參考 | MDN
IntersectionObserver API 使用教程 - 阮一峰
程式碼實現
下方附帶github原始碼
class LazyLoad{
constructor(images, options = {}) {
this.setting = Object.assign({}, {src: 'data-src', srcset: 'data-srcset'}, options)
this.images = images
this.observer = null
this.init()
}
init() {
let observerConfig = {
root: null,
rootMargin: '0px',
threshold: [0]
}
this.observer = this.intersectionObserver(observerConfig)
this.images.forEach(image => this.observer.observe(image))
}
}
複製程式碼
- observerConfig中的屬性
root
: 檢視節點,null時預設為body(應該是)rootMargin
根元素的marginthreshold
屬性決定了什麼時候觸發回撥函式。它是一個陣列,每個成員都是一個門檻值,預設為[0],即交叉比例(intersectionRatio)達到0時觸發回撥函式
生成IntersectionObserver
例項
intersectionObserver(config) {
return new IntersectionObserver(entries => {
entries.forEach(entry => {
const target = entry.target
// 到元素出現在檢視中
if(entry.intersectionRatio > 0) {
this.observer.unobserve(target)
// 設定img真實src路徑
this.setImgsrc(target)
}
})
}, config)
}
複製程式碼
設定img真實src路徑
setImgsrc(target){
const src = target.getAttribute(this.setting.src)
const srcset = target.getAttribute(this.setting.srcset)
// 判斷是否為img節點
if('img' === target.tagName.toLowerCase()) {
if(src) {
target.src = src
}
if(srcset) {
target.srcset = srcset
}
} else {
target.style.backgroundImage = `url(${src})`
}
}
複製程式碼
新增全域性設定
這一個步驟可能多餘了,但是在實現元件的時候經常會有全域性設定,方面更改
const glabolConfig = {
src: 'data-src',
srcset: 'data-srcset'
}
class LazyLoad{
constructor(images, options = {}, glabolConfig) {
this.setting = Object.assign({}, glabolConfig, options)
}
}
複製程式碼
保護區域性變數
;(function(window, glabolConfig) {
class LazyLoad{
...
}
})(window, glabolConfig);
複製程式碼
無new生成例項
window.lazyLoad = (images, options = {}) =>{
return new LazyLoad(images, options, glabolConfig)
}
複製程式碼
使用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
img, body, ul, li, html {
margin: 0;
padding: 0;
}
img{
height: 700px;
width: 100vw;
}
</style>
</head>
<body>
<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 src="js/intersectionObserver-lazyload.js"></script>
<script>
let imgItems = [...document.querySelectorAll('img')];
lazyLoad(imgItems)
</script>
</body>
</html>
複製程式碼