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>
复制代码