We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
年底相关活动页需要一些比较密集的图片显示,且好几条业务线都有类似的需求,用高阶组件的形式来搞吧,正好前几天看上了个新api,写一下相关总结
正常来讲,懒加载往往是通过clientHeight,scrollTop,offsetTop来计算当前元素是否出现在视口中,也就是要监听scroll方法。如下:
clientHeight
scrollTop
offsetTop
scroll
startLazyLoad = () => { //比如所有的img元素的class都是lazy let count = 0; const lazy = document.querySelectorAll('.lazy'); const clientHeight = document.documentElement.clientHeight; const scrollTop = document.documentElement.scrollTop; for (let i = 0; i < lazy.length; i++) { if (lazy[i].offsetTop < clientHeight + scrollTop) { lazy[i].src = lazy[i].getAttribute('data-src'); count++ } } if (count === lazy.length) { window.removeEventListener('scroll', this.startLazyLoad) } } window.addEventListener('scroll', this.startLazyLoad); //有条件的加个节流
ps:判断是否到底的话可以这么用element.scrollHeight - element.scrollTop === element.clientHeight
element.scrollHeight - element.scrollTop === element.clientHeight
调用IntersectionObserver时,需要给它传一个回调函数 / 对象。当监听的dom元素进入可视区域或者从可视区域离开时,回调函数就会被调用。
const io = new IntersectionObserver((entries) => { console.log(entries); }); io.observe(dom);
在new的时候会调用一次,这点可以解决初始进入页面时候的懒加载问题 在监听元素进入/移出的时候会调用,callback中会传入一串数组,有这么几个属性:
target: 被观察的目标元素,是一个 DOM 节点对象
isIntersecting: 是否进入可视区域
intersectionRatio: 相交区域和目标元素的比例值,进入可视区域,值大于0,否则等于0(这个基本上用处没有第二点多)
基于以上几点,我们可以实现这么一个懒加载,包含了自动监听滚动时间,判断视口,且节流。
startObserveImg = () => { const lazy = document.querySelectorAll('.lazy'); const observer = new IntersectionObserver(observers => { //observers表示此刻移出或者进入视口的所有img列表 for (let i = 0; i < lazy.length; i++) { const ob = observers[i]; if (ob.isIntersecting) { const element = ob.target setTimeout(() => { element.src = element.getAttribute('data-src') }, 1000) observer.unobserve(element) } } }) lazy.forEach(item => observer.observe(item)) }
兼容层面来说不是很理想,但是大部分可用,在safari或者hybrid下的WKwebview好像还不太行,安卓还没试过,最好需要判断一下当前环境。
import ImgLazyLoadHOC from './B.js' //A.js render() { const imgList = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24] function imgDom(props) { const { imgLazyContainer } = props; return ( <div className="imgsDiv"> {imgLazyContainer} </div> ) } const ImgDomComponent = ImgLazyLoadHOC(imgDom, { imgList: imgList }) return( <ImgDomComponent /> ) }
//B.js import React, { Component } from 'react' const ImgLazyLoadHOC = (WarpComponent, config = {}) => { const { imgList } = config; const imgLazyMapList = imgList && imgList.map(() => { return <img className="lazy" src="default.png" data-src="target.png"/> }) return class ImgLazyLoadFuncHOC extends Component { componentDidMount() { this.checkObserverAbility() ? this.startObserveImg() : this.startLazyLoadImg() } //use IntersectionObserver or common way checkObserverAbility = () => { return !!window.IntersectionObserver } startLazyLoadImg = () => { this.startLazyLoad() window.addEventListener('scroll', this.startLazyLoad); } startLazyLoad = () => { let count = 0; const lazy = document.querySelectorAll('.lazy'); const clientHeight = document.documentElement.clientHeight; const scrollTop = document.documentElement.scrollTop; for (let i = 0; i < lazy.length; i++) { if (lazy[i].offsetTop < clientHeight + scrollTop) { lazy[i].src = lazy[i].getAttribute('data-src'); count++ } } if (count === lazy.length) { window.removeEventListener('scroll', this.startLazyLoad) } } startObserveImg = () => { const lazy = document.querySelectorAll('.lazy'); const observer = new IntersectionObserver(observers => { for (let i = 0; i < lazy.length; i++) { const ob = observers[i]; if (ob.isIntersecting) { const element = ob.target setTimeout(() => { element.src = element.getAttribute('data-src') }, 1000) observer.unobserve(element) } } }) lazy.forEach(item => observer.observe(item)) } render() { return <WarpComponent imgLazyContainer={imgLazyMapList}/> } } } export default ImgLazyLoadHOC
感谢深红大大:IntersectionObserve初试
The text was updated successfully, but these errors were encountered:
No branches or pull requests
年底相关活动页需要一些比较密集的图片显示,且好几条业务线都有类似的需求,用高阶组件的形式来搞吧,正好前几天看上了个新api,写一下相关总结
正常来讲,懒加载往往是通过
clientHeight
,scrollTop
,offsetTop
来计算当前元素是否出现在视口中,也就是要监听scroll
方法。如下:ps:判断是否到底的话可以这么用
element.scrollHeight - element.scrollTop === element.clientHeight
IntersectionObserver,MDN
调用IntersectionObserver时,需要给它传一个回调函数 / 对象。当监听的dom元素进入可视区域或者从可视区域离开时,回调函数就会被调用。
关于调用次数
在new的时候会调用一次,这点可以解决初始进入页面时候的懒加载问题
在监听元素进入/移出的时候会调用,callback中会传入一串数组,有这么几个属性:
target: 被观察的目标元素,是一个 DOM 节点对象
isIntersecting: 是否进入可视区域
intersectionRatio: 相交区域和目标元素的比例值,进入可视区域,值大于0,否则等于0(这个基本上用处没有第二点多)
基于以上几点,我们可以实现这么一个懒加载,包含了自动监听滚动时间,判断视口,且节流。
兼容层面来说不是很理想,但是大部分可用,在safari或者hybrid下的WKwebview好像还不太行,安卓还没试过,最好需要判断一下当前环境。
完全版,一些react的语法就不添加了:
参考
感谢深红大大:IntersectionObserve初试
The text was updated successfully, but these errors were encountered: