• 【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
            }
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    效果图:(待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)
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    效果图:(待gif)

    • 注意 控制台 只要 懒加载完成后,监听就被取消了
      在这里插入图片描述

    拓展

    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
          } ```
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12

    示意图


    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) 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 当然,这个API 的好用之处不止在于用于 懒加载,还用许多场景可用,待探索🤩(可见参考文章)

    innerWidht + innerHeight

    菜鸟教程___Window innerWidth 和 innerHeight 属性

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

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

    innerWidth 和 innerHeight 是只读属性。

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


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

    BOM window 有关高宽的属性

    - .innerWidht  .innerHeight
    - .outterWidht  .outterHeight
    - .screenX  .screenY
    
    • 1
    • 2
    • 3

    DOM element 有关高宽的属性

    - .clientTop  .clientLeft 
    - .clientWidth .clientHeight
    - .offsetTop  .offsetLeft
    - .offsetWidth .offsetHeight
    - .scrollTop  .scrollLeft
    - .scrollWidth .scrollHeight
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    本文例子所用的 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="">
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
  • 相关阅读:
    JWT认证、drf-jwt安装和简单使用、实战之使用Django auth的User表自动签发、实战之自定义User表,手动签发
    自定义View:多点触控(二)-- 多指协作
    2022-11-09 git笔记:git第二次提交,git多人提交
    Unity之NetCode多人网络游戏联机对战教程(1)
    每天学习3个小时能不能考上浙大MBA项目?
    java项目 基于springboot儿童福利院申请管理系统
    推荐几款简单易用的协作化项目管理工具
    如何将JACOCO应用到企业实战中~测试过招,只需6点
    【Selenium】Selenium4 Grid
    Day 57 django 路由系统 反向解析
  • 原文地址:https://blog.csdn.net/m0_61486963/article/details/126519811