【UN-JS-工具类】懒加载的实现 -- 两种方式 --- 一种5行JS实现懒加载

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

  • 方法一:scroll + getBoundingClientRect
  • 方法二:IntersectionObserver(推荐)

codepen 展示

lazyLoad-scroll-getBoundingClientRect-SAM9029
lazyload-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)

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

【UN-JS-工具类】懒加载的实现 -- 两种方式 --- 一种5行JS实现懒加载_第1张图片


二: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)

  • 注意 控制台 只要 懒加载完成后,监听就被取消了
    【UN-JS-工具类】懒加载的实现 -- 两种方式 --- 一种5行JS实现懒加载_第2张图片

拓展

getBoundingClientRect Api

MDN-Element.getBoundingClientRect()

  • Element.getBoundingClientRect() 是一个无参普通函数方法
  • 返回一个 DOMRect 对象,其提供了元素的大小及其相对于视口的位置。
  • 注意视口可☞window,也可指具有滚动条的父元素!!!
    • 返回值是一个对象,其中有(以下为示意例子):
    •   {   
            //元素大小信息
            height: 120
            width: 100
            //元素在窗口的位置信息
            top: 571.5
            left: 18
            bottom: 691.5
            right: 118
            y: 571.5
            x: 18
        } ```
      

示意图

【UN-JS-工具类】懒加载的实现 -- 两种方式 --- 一种5行JS实现懒加载_第3张图片


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 属性获取浏览器窗口的宽度与高度。


所有有关 DOM 和 BOM 操作高宽的API

BOM window 有关高宽的属性

- .innerWidht  .innerHeight
- .outterWidht  .outterHeight
- .screenX  .screenY

DOM element 有关高宽的属性

- .clientTop  .clientLeft 
- .clientWidth .clientHeight
- .offsetTop  .offsetLeft
- .offsetWidth .offsetHeight
- .scrollTop  .scrollLeft
- .scrollWidth .scrollHeight

本文例子所用的 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="">

你可能感兴趣的:(JS学习,javascript,前端,开发语言)