怎么写一个树形穿梭框

news2024/10/2 16:25:47

图片懒加载基本原理

所谓图片懒加载,就是需要展示图片的时候再加载,当图片没有进入我们的视觉范围内的时候,图片还没有加载,只用一个占位符或者 loading 图片替代。当我们滚动页面时,占位符或者 loading 图片进入到我们的视觉范围,就加载图片。这样可以解决一次性加载大量图片带来的性能问题

为了实现图片懒加载有两个核心问题需要解决

1.如何判断图片已经在可视区域范围内?
2.图片进入可视区域后,如何触发加载图片

对于第二个问题需要用到 DOM 元素的 dataset 属性,所有以 data- 开头的属性都可以用做自定义属性,所以我们可以定义一个 data-src 属性存放需要加载的图片链接,src 属性使用 loading 占位图片,当需要加载图片的时候,把 src 的链接更换为 data-src 的链接即可

<img data-src="需要加载的图片链接" src="loading 图片链接"> 

所以剩下要解决的是第一个问题:如何判断图片进入可视区域内?

方案一:getBoundingClientRect()

这个方案需要获取两个高度:浏览器窗口高度(可视区域高度)和元素距离浏览器窗口顶部的高度

浏览器窗口高度通过 document.documentElement.clientHeight 这个 API 来获取,另外我也在网上找了一张浏览器常用高度的示意图供大家参考

获取元素距离可视区域顶部的高度需要通过getBoundingClientRect() API 来实现,getBoundingClientRect() 获取的是 DOM 元素相对于窗口的坐标集合,集合中有多个属性,其中的 top 属性就是当前元素元素距离窗口可视区域顶部的距离(下图是所有距离属性的示意图)

有了这两个高度判断的 API,实现方案就简单了,通过监听当前可视区域的高度 - 元素距离可视区域顶部的高度,当这个高度差小于 0 时说明图片已经进入可视区域,这时开始加载图片

// 获取所有图片标签
const imgs = document.getElementsByTagName("img");
// 获取可视区域的高度
const viewHight = document.documentElement.clientHeight;
// 统计当前加载到了哪张照片,避免每一次都从第一张照片开始检查
let num = 0;

function lazyload() {for (let i = num; i < imgs.length; i++) {const item = imgs[i]// 可视区域高度减去元素顶部距离可视区域顶部的高度,如果差值大于 0 说明元素展示let distance = viewHight - item.getBoundingClientRect().top;if (distance >= 0) {// 展示真实图片
	item.src = item.getAttribute("data-src");num = i + 1;}}
}

// 监听 scroll 事件
window.addEventListener("scroll", lazyload, false);

lazyload(); 

下面是我使用马上掘金实现的一个小 demo,大家可以直接体验一下效果

但是使用这个方案有一个弊端,就是 scroll 是同步事件,在滚动时需要大量计算,很容易造成性能问题,所以会需要配合节流方法一起使用。所以对于这个问题,还有没有其他更好的方案呢?

方案二:Intersection Observer

IntersectionObserver 提供了一种异步观察目标元素与其祖先元素或 viewport 交叉状态的方法,可以通过浏览器全局访问,目的就是为了解决监听 scroll 同步事件带来的性能问题

IntersectionObserver(callback, options) 方法有两个参数,下面分别介绍一下这两个参数

callback 参数:当元素可见性变化时执行的回调函数,所以当元素进入时会触发一次 callback ,离开时还会触发一次 callbackcallback 函数有一个 entries 作为入参,entries 是一个对象,有 7 个属性,前两个属性很重要,是用于实现图片懒加载的核心属性

  • target:观察的目标 DOM 元素
  • isIntersecting:目标元素 target 当前是否可见,可见为 true
  • time:返回一个记录从 IntersectionObserver 的时间到交叉被触发的时间的时间戳
  • rootBounds:根元素的矩形区域的信息,getBoundingClientRect() 方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回 null
  • boundingClientRect:目标元素的矩形信息
  • intersectionRatio:相交区域和目标元素的比例值 intersectionRect/boundingClientRect 不可见时小于等于0
  • intersectionRect:目标元素和视窗(根)相交的矩形信息

虽然剩余 5 个属性暂时还用不上,但是为了方便大家理解这 5 个属性,我还是画了一个示意图

options 是可选参数配置,主要有三个属性

  • root:监听对象的祖先元素,一般都是默认为 root
  • thresholds:阈值列表,决定什么时候触发 callback 函数。默认是 0,就是当目标元素刚出现在交界处时就会触发 callback 函数
  • rootMargin:扩大或缩小 viewport 的范围,可以理解为划定一个范围

另外 IntersectionObserver 还有三个方法,用于启动和停止监听

  • IntersectionObserver.observe():开始监听
  • IntersectionObserver.disconnect():停止监听
  • IntersectionObserver.unobserve(element):停止监听特定的 element 元素

有了上面这些基础知识的铺垫之后,下面是图片懒加载方法实现的核心代码,原理也是一样,在当前元素可见时把 src 替换为 data-src 中的真实链接

const io = new IntersectionObserver((entries) => {entries.forEach(item => {// 当前元素可见时if(item.isIntersecting) {item.target.src = item.target.dataset.src // 替换 srcio.unobserve(item.target) // 停止观察当前元素,避免不可见时再次调用 callback 函数}})
})

const imgs = document.querySelectorAll('[data-src]')

// 监听所有图片元素
imgs.forEach(item => {io.observe(item)
}) 

同样附上 demo 链接体验一下效果

从浏览器兼容性的角度看,IntersectionObserver 也兼容了大部分浏览器,如果大家没有特别的浏览器兼容需要,完全可以使用这个性能更好的方法来实现图片懒加载

最后

为大家准备了一个前端资料包。包含54本,2.57G的前端相关电子书,《前端面试宝典(附答案和解析)》,难点、重点知识视频教程(全套)。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/95327.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]Python计算机毕业设计Django绿色生活交流社区网站

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

部门来了个测试开发,听说是培训生,上来一顿操作给我看呆了...

&#x1f4cc; 博客主页&#xff1a; 程序员二黑 &#x1f4cc; 专注于软件测试领域相关技术实践和思考&#xff0c;持续分享自动化软件测试开发干货知识&#xff01; &#x1f4cc; 公号同名&#xff0c;欢迎加入我的测试交流群&#xff0c;我们一起交流学习&#xff01; 前段…

大数据呀大数据

大数据 啥是大数据? 我自己的一些经历–>>在做代码开发之前,一直觉得大数据这件事是高大上的一门学问,门槛很高,而且我上大学的时候这个词才刚刚在众多互联网记住中展露头角; 我的个人经历–>> 我上大学时那时候安卓的版本才到安卓4.4,在智能手机出来普及以前,各…

STM32 10个工程实战前言

从今年2022年元旦开通博客到现在基本接近一年了&#xff0c;真的会感到感觉时间飞逝&#xff0c;尤其当你全身心地投入一件工作上时&#xff0c;在FPGA基础篇和FPGA 20个经理例程篇后&#xff0c;又准备了STM32基础篇和STM32 10个工程实战篇&#xff0c;前两者即将收尾&#xf…

外汇天眼:欧洲央行加息50基点!加息的步伐将会放缓

欧洲央行(European Central Bank)在周四的会议上选择小幅加息&#xff0c;将基准利率从1.5%上调至2%。而其主要再融资操作和边际贷款工具的借贷成本分别升至2.50%和2.75%。 它还表示&#xff0c;从2023年3月初开始&#xff0c;到2023年第二季度末&#xff0c;它将开始平均每月减…

付费视频被人薅走?了解一下hls视频加密

前言 作者现在主要负责的项目是通过音视频等课程提高教师职业能力的&#xff0c;说白了就是给老师卖课赚钱。大家都知道知识付费现在还是很火的&#xff0c;既然是要付费的知识&#xff0c;就肯定有人想白嫖&#xff0c;直接去下载课程里面音视频。业界就有很多工具&#xff0…

世界杯观赛调研公布: Z世代消费者首选海信电视

2022世界杯决赛在即&#xff0c;作为观赛主体的Z世代迎来了四年一度的足球狂欢季。12月12日&#xff0c;市场研究机构千趣GKURC&#xff08;关键用户调查研究中心&#xff09;发布了《Z世代2022世界杯观赛和消费行为特征》调查报告&#xff08;以下简称报告&#xff09;。 报告…

图解设计模式:Teamplate Method 模板方法模式 由子类实现具体内容的模式

前言 &#x1f4e3; &#x1f4e3; &#x1f4e3; &#x1f4e2;&#x1f4e2;&#x1f4e2; ☀️☀️点开就是缘分认识一下&#xff0c;我是小冷。是一个兴趣驱动自学练习两年半的的Java工程师。 &#x1f4d2; 一位十分喜欢将知识分享出来的Java博主⭐️⭐️⭐️&#xff0c;…

ChatGPT的博弈:一场猫捉老鼠的游戏画上句号

前言 上周日我在B站发了个视频(https://www.bilibili.com/video/BV1Ud4y1e7BP)&#xff0c;本来想水一期的(毕竟一个半月没更新了)&#xff0c;不过借着ChatGPT的热度&#xff0c;播放量突破2w。 随之而来的是大批网友涌入群聊&#xff0c;想测验一下ChatGPT的性能&#xff0…

手把手教你在Ubuntu定制文件系统

为了给客户的测试和开发提供便利&#xff0c;飞凌嵌入式的开发板产品一般都支持多种操作系统&#xff0c;以基于全志T507H处理器设计研发的OKT507-C开发板为例&#xff0c;它支持三种操作系统&#xff0c;分别是&#xff1a;Linux、Android 和 Forlinx Desktop&#xff08;Ubun…

招聘惊现997工作要求!HR:因为下班比较晚,所以公司一般不加班

对于程序员来说&#xff0c;加班就像阳光和空气&#xff0c;实在是太正常不过的事情了。 就算本身并不是需要加班的公司&#xff0c;在项目上线的前夕多多少少肯定还是需要加一些班的&#xff01; 但是&#xff0c;下面这家公司就不一样了&#xff0c;直言公司就是997工作制……

Centos 配置磁盘加密(crypt-disk)

文章目录 Crypt-disk 创建一块新的磁盘,启用磁盘加密,解锁密码为“CSK2022!”; 映射到/dev/mapper/crypt 分区,并挂载到/mut/crypt 目录。一、去虚拟机添加一块磁盘二、安装cryptsetup2.对/dev/sdb 进行加密操作3.映射加密磁盘4.格式化5.挂载到到/mut/crypt 目录。题目 Cry…

Pytest测试框架(二):fixture 方法等相关操作--自定义测试用例的前置后置条件

pytest中的fixture&#xff1a; fixture是pytest特有的功能&#xff0c;它用pytest.fixture标识&#xff0c;定义在函数前面。fixture有明确的名字&#xff0c;在其他函数&#xff0c;模块&#xff0c;类或整个工程调用它时会被激活。fixture是基于模块来执行的&#xff0c;每个…

如何用C#制作 微信个人机器人

打包下载..https://github.com/wechaty/dotnet-wechaty在windows上安装docker&#xff0c;由于可能不是专业版windows10&#xff0c;可能会遇到一系列问题&#xff0c;百度能解决。可以参考 win10安装docker&#xff08;适用于windows家庭版&#xff09;_一起玩编程的博客-CSDN…

基于jsp+mysql+SSM学生兼职信息网站-计算机毕业设计

项目介绍 运行环境: 最好是java jdk 1.8&#xff0c;我们在这个平台上运行的。其他版本理论上也可以。 IDE环境&#xff1a; Eclipse,Myeclipse,IDEA都可以 tomcat环境&#xff1a; Tomcat 7.x,8.x,9.x版本均可 硬件环境&#xff1a; windows 7/8/10 1G内存以上 管理员角色…

系统的混乱并非业务本身之复杂,我们并不擅长处理『简单』

作者&#xff1a;聂晓龙 一、前言 一群高智商青年在餐厅吃饭&#xff0c;餐桌上一个瓶盖标识为盐的瓶子里装的是胡椒粉&#xff0c;而标识为胡椒粉的瓶子里装的却是盐&#xff0c;他们想出了一个充满才气的方案来完成对调--仅需要一张餐巾纸、一根吸管和两个空碟子。当他们叫来…

Jmeter 性能测试入门 ——性能插件介绍

目录 一、前言 1、首先&#xff0c;JMeter提供了三个基本的线程组&#xff0c;分别为: 2、其他线程组可以通过集成插件的方式使用&#xff0c;包括&#xff1a; 二、集成插件下载安装 1、下载地址&#xff1a;jmeter-plugins.org 2、安装&#xff1a;下载后文件为plugins…

nodejs+vue015疫情社区管理系统

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.3 B/S结构 4 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可…

Python自学教材推荐 初学者必看

Python是一种面向对象、解释性的高级程序语言&#xff0c;它已经被应用在众多领域&#xff0c;因此学习Python变得越来越有必要。传智播客针对编程零基础的初学者&#xff0c;编著出版了高质量的Python自学教材——《Python快速编程入门》。下面我将把这本书推荐给大家&#xf…

陈天老师的Rust培训(1)学习笔记

https://tyrchen.github.io/rust-training/ 跟C互操作时&#xff0c;加上上面图片的宏&#xff0c;rust会根据你的各个域的内存的占用自动去调整内存中的位置&#xff0c;让你的内存占用是最优的&#xff0c;而且rust在生成数据结构的结构的时候&#xff0c;它会做一些padding&…