写点什么

【JS】两种实现 - 懒加载的方式 - 附无限滚动案例

作者:Sam9029
  • 2022 年 9 月 09 日
    四川
  • 本文字数:3805 字

    阅读完需:约 12 分钟

【JS】两种实现-懒加载的方式-附无限滚动案例

🦖我是 Sam9029,一个前端

Sam9029 的 InfoQ 主页:Sam9029 (infoq.cn)

**🐱‍🐉🐱‍🐉恭喜你,若此文你认为写的不错,不要吝啬你的赞扬,求收藏,求评论,求一个大大的赞!👍**

懒加载的实现 (两种方式)

  • 方法一:scroll + getBoundingClientRect

  • 方法二:IntersectionObserver(推荐)

codepen 展示

lazyLoad-scroll-getBoundingClientRect-SAM9029lazyload-IntersectionObserver-SAM9029


进阶--利用 getBoundingClientRect 实现图片的无限滚动加载 无限滚动懒加载--getBoundingClientRect


  • 关于上诉 API 在拓展中有使用介绍!!

  • html+css 代码在文章最后(也可在 codepen 拿到)



一:scroll + getBoundingClientRect

  • 思路:使用 scroll 事件实时检测 目标图像元素的 是否出现的 浏览器(或拥有滑动块的元素)的可视视图内

  • 若是 在浏览器视图内懒加载 利用 window.innerHeight 和 目标图像元素.getBoundingClientReact().top 来作比较

  • 若是 在拥有滑动块元素视图内懒加载 利用 el.offsetHeight 和 目标图像元素.getBoundingClientReact().top 来作比较

😱缺点:懒加载后无法取消监听,浪费性能

codepen 展示

lazyLoad-scroll-getBoundingClientRect-SAM9029

源码:

let imgList = document.querySelectorAll('img')window.onscroll = function() {    console.log('执行懒加载监听')    //imgList 本身是 类数组含有 forEach方法同理实现    //此处使用 map 调用call 只是为了加深 改变执行上下文的方法 使用,不必在意    Array.prototype.map.call(imgList,item =>{        // 目标 对象 距离 xx 的顶部距离 小于 当前浏览器窗口的可视高度        if(item.getBoundingClientRect().top < window.innerHeight){            // 将 存储 在data自定义属性中的src 提出 赋值给 img的src            item.src = item.dataset.src        }    })}
复制代码

效果图:(待 gif)

  • 注意 控制台 只要 懒加载完成后,监听依然在执行




二:IntersectionObserver(推荐)

  • 思路:使用 IntersectionObserver (此为构造函数)的 observe 属性方法,判断目标元素是否出现在可视视图中

😱缺点:

  • 暂时没想到(该 API 好像兼容性要考虑),IntersectionObserver 的 unobserve 取消观察完全弥补第一种方法的缺点

codepen 展示

lazyload-IntersectionObserver-SAM9029

源码:

let imgList = document.querySelectorAll('img')
let imgObserver = new IntersectionObserver(callback)
//我把callback 写在 外面,方便理解,亦可直接写在构造函数参数内function callback(entries){ console.log('执行懒加载监听') //被观察的 图片数组对象 entries.forEach(item=>{ // 调用 被观察的目标元素 是否 与可视窗口 出现交叉区域 if(item.isIntersecting){ //获取 被观察的目标元素 const targetImg = item.target // 将 存储 在data自定义属性中的src 提出 赋值给 img的src targetImg.src = targetImg.dataset.src // 在懒加载完成后可执行 停止观察,节约性能资源 imgObserver.unobserve(targetImg) } })}
//每个图片都进行观察imgList.forEach(item=>{ imgObserver.observe(item)})
复制代码

效果图:(待 gif)

  • 注意 控制台 只要 懒加载完成后,监听就被取消了



拓展

getBoundingClientRect Api

MDN-Element.getBoundingClientRect()


  • Element.getBoundingClientRect() 是一个无参普通函数方法

  • 返回一个 DOMRect 对象,其提供了元素的大小及其相对于视口的位置。

  • 注意视口可☞window,也可指具有滚动条的父元素!!!

  • 返回值是一个对象,其中有(以下为示意例子):


js   {      //元素大小信息   height: 120   width: 100   //元素在窗口的位置信息   top: 571.5   left: 18   bottom: 691.5   right: 118   y: 571.5   x: 18   } 
复制代码




IntersectionObserver Api

👍超好用的API之IntersectionObserver-掘金-Va007


  • 基本使用讲解:

  • 这个 API 叫做"交叉观察器": 观察目标元素与视口是否产生一个交叉区

  • 注意:这个 API 是 一个 !!⭐构造函数,

  • 基本语法 let targetImgObserver = new IntersectionObserver(callback, option);

  • callback 必填(用于执行交叉观察函数时,申明做什么操作!!)

  • option 是配置对象(该参数可选)

  • 该 构造函数 有两个原型的内置方法 (_target 需要被观察的对象节点)

  • targetImgObserver.observe(_target) : 监听目标对象

  • targetImgObserver.unobserve(_target) : 停止监听目标对象(该方法可用在图片加载为成功后执行)

  • 再讲回构造函数的参数 callback 回调函数 (理解起来可能有些难,多看几遍参考文章,多写几遍代码!!)

  • callback 函数本省也有 参数_entries 一般写成 箭头函数的形式(见基本使用语法)

  • 关于 参数 _entries 我们需要知道 这就是构造函数的 .observe(_target)方法调用后拿到的 目标对象(可接受为数组形式,即我们多个对象进行了观察,这种情况下很多见,可结合本次例子理解),并可以调用其的观察信息属性

  • 常用的 entries.isIntersecting :返回一个布尔值,下列两种操作均会触发 callback:1. 如果目标元素出现在 root 可视区,返回 true。2. 如果从 root 可视区消失,返回 false

  • entries.target 目标元素:即被观察的目标元素

  • 基本使用语法


    let targetImgObserver = new IntersectionObserver(callback = _entries =>{            //code        }, option);    //调用该 观察方法后,回调函数的 _entries 就会拿到 被观察的对象    targetImgObserver.observe(_target)     // 在懒加载完成后可执行 停止观察    // targetImgObserver.unobserve(_target) 
复制代码


  • 当然,这个 API 的好用之处不止在于用于 懒加载,还用许多场景可用,待探索🤩(可见参考文章)



innerWidht + innerHeight

菜鸟教程___Window innerWidth 和 innerHeight 属性


  • innerHeight 返回窗口的文档显示区的高度,如果有垂直滚动条,也包括滚动条高度。

  • innerWidth 返回窗口的文档显示区的宽度,如果有水平滚动条,也包括滚动条高度。


innerWidth 和 innerHeight 是只读属性。


注意:使用 outerWidth 和 outerHeight 属性获取浏览器窗口的宽度与高度。


本文例子所用的 HTML+CSS 源码

    <style>        img{            display: block;            margin: 10px;            width: 100px;            height: 120px;        }    </style>        <!-- 文字 -->    <div>        <div>            <h1>清平乐·六盘山</h1>            <p>                天高云淡,望断南飞雁。            </p>            <p>                不到长城非好汉,屈指行程二万。            </p>            <p>                六盘山上高峰,红旗漫卷西风。            </p>            <p>                今日长缨在手,何时缚住苍龙?            </p>        </div>        <div>            <h1>清平乐·六盘山</h1>            <p>                天高云淡,望断南飞雁。            </p>            <p>                不到长城非好汉,屈指行程二万。            </p>            <p>                六盘山上高峰,红旗漫卷西风。            </p>            <p>                今日长缨在手,何时缚住苍龙?            </p>        </div>        <div>            <h1>清平乐·六盘山</h1>            <p>                天高云淡,望断南飞雁。            </p>            <p>                不到长城非好汉,屈指行程二万。            </p>            <p>                六盘山上高峰,红旗漫卷西风。            </p>            <p>                今日长缨在手,何时缚住苍龙?            </p>        </div>        <div>            <h1>清平乐·六盘山</h1>            <p>                天高云淡,望断南飞雁。            </p>            <p>                不到长城非好汉,屈指行程二万。            </p>            <p>                六盘山上高峰,红旗漫卷西风。            </p>            <p>                今日长缨在手,何时缚住苍龙?            </p>        </div>    </div>    <img data-src='https://i.postimg.cc/QdzdhHzg/i001.jpg' alt="">    <img data-src='https://i.postimg.cc/RF7S7GZG/i002.jpg' alt="">    <img data-src='https://i.postimg.cc/gJFcL1mn/i003.jpg' alt="">    <img data-src='https://i.postimg.cc/ZqyKRJkG/i004.jpg' alt="">data-src='https://i.postimg.cc/QdzdhHzg/i001.jpg' alt="">    <img data-src='https://i.postimg.cc/RF7S7GZG/i002.jpg' alt="">    <img data-src='https://i.postimg.cc/gJFcL1mn/i003.jpg' alt="">    <img data-src='https://i.postimg.cc/ZqyKRJkG/i004.jpg' alt="">
复制代码



无限滚动懒加载效果案例

  • 使用了第一种方式 getBoundingClientRect 加 onscroll 监听实现

  • 第二种 IntersectionObserver 同理,可自行拓展实现


源码

【Codepen.io--Sam9029】-无限滚动懒加载--getBoundingClientRect


🦖我是 Sam9029,一个前端,坚信应无所往

文章若有错误,敬请指正🙏

**🐱‍🐉🐱‍🐉恭喜你,都看到这了,求收藏,求评论,求一个大大的赞👍!不过分吧**

Sam9029 的 InfoQ 主页:[Sam9029 (infoq.cn)](

发布于: 刚刚阅读数: 5
用户头像

Sam9029

关注

庸俗 2022.09.03 加入

好色

评论

发布
暂无评论
【JS】两种实现-懒加载的方式-附无限滚动案例_JavaScript_Sam9029_InfoQ写作社区