当前位置: 首页 > news >正文

【懒加载】js实现懒加载、vue实现图片懒加载指令

懒加载

延迟加载,对于一个很长的页面,优先加载可视区域的内容,其他部分等进入可视区域时再加载

懒加载作用

是一种网页性能优化的方式,它能极大的提升用户体验。比如一个页面中有很多图片,但是首屏只出现几张,这时如果一次性把图片全部加载出来会影响性能。这时可以使用懒加载,页面滚动到可视区再加载。优化首屏加载。

图片懒加载

监听滚动条滚动事件,当视口的高度+滚动高度,大于图片所在位置举例顶部的偏移量时(也就是距离),加载图片资源

index.html

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div style="height: 1200px;"></div><img src="https://ts2.cn.mm.bing.net/th?id=OIP-C.Fi0rA6s5NQ1VIlwp9IzhIgHaKe&w=210&h=297&c=8&rs=1&qlt=90&o=6&pid=3.1&rm=2"data-src="https://ts3.cn.mm.bing.net/th?id=OIP-C.D-43aYLc7We_sO_5ZSMIXgHaFj&w=288&h=216&c=8&rs=1&qlt=90&o=6&pid=3.1&rm=2" /><script>let img = document.getElementsByTagName("img");let num = img.length;let count = 0; lazyload();window.addEventListener('scroll', lazyload); function getTop(el) {var T = el.offsetTop;// 迭代地获取元素及其父元素相对于文档顶部的累积偏移量while (el = el.offsetParent) {T += el.offsetTop;}// 循环后 返回元素相对于文档顶部的总偏移量return T;}function lazyload() {//视口高度let viewHeight = document.documentElement.clientHeight || document.body.clientHeight;//滚动高度let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;for (let i = count; i < num; i++) {// 元素现在已经出现在视口中if (getTop(img[i]) < scrollTop + viewHeight) {// 如何图片等于默认图 则加载新图if (img[i].getAttribute("src") !== "https://ts2.cn.mm.bing.net/th?id=OIP-C.Fi0rA6s5NQ1VIlwp9IzhIgHaKe&w=210&h=297&c=8&rs=1&qlt=90&o=6&pid=3.1&rm=2") continue;img[i].src = img[i].getAttribute("data-src");count++;} else {break;}}}</script>
</body></html>

使用浏览器提供的getBoundingClientRect(),优化上述代码: lazyload修改如下:

getBoundingClientRect()用于获取元素相对于视口的位置信息

        function lazyload() {let viewHeight = document.documentElement.clientHeight || document.body.clientHeight;for (let i = count; i < num; i++) {// getBoundingClientRect() 用于获取元素相对于视口的位置信息// 当相对于视口位置 小于等于视口时说明图片已经可见了if (img[i].getBoundingClientRect().top < viewHeight) {if (img[i].getAttribute("src") !== "https://ts2.cn.mm.bing.net/th?id=OIP-C.Fi0rA6s5NQ1VIlwp9IzhIgHaKe&w=210&h=297&c=8&rs=1&qlt=90&o=6&pid=3.1&rm=2") continue;img[i].src = img[i].getAttribute("data-src");count++;} else {break;}}}

使用IntersectionObserver()再次优化上述代码

IntersectionObserver是浏览器原生提供的构造函数,用于查看某个元素是否进入了视口(viewport),用户能否看到该元素

修改上述代码:

    <script>let img = document.getElementsByTagName("img");const observer = new IntersectionObserver(changes => {console.log(changes)//changes 是被观察的元素集合for (let i = 0, len = changes.length; i < len; i++) {let change = changes[i];// 通过这个属性判断是否在视口中if (change.isIntersecting) {const imgElement = change.target;imgElement.src = imgElement.getAttribute("data-src");// IntersectionObserver 对象的一个方法,用于停止对指定元素的观察observer.unobserve(imgElement);}}})Array.from(img).forEach(item => {observer.observe(item)});</script>

内容懒加载:

一个页面有n条订单,每次可以给他显示10条,等用户拖动滚动条滚动到订单列表底部一段距离时再显示10条,直到加载完

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>span {display: block;}</style>
</head><body><div style="height: 1200px;">1</div><div class="box"><span>开始</span></div><script>let div = document.getElementsByClassName("box")[0];let lastSpanElement = div.querySelector('span:last-child');const observer = new IntersectionObserver(changes => {console.log(changes)//changes 是被观察的元素集合for (let i = 0, len = changes.length; i < len; i++) {let change = changes[i];// 通过这个属性判断是否在视口中if (change.isIntersecting) {for (let i = 0; i < 10; i++) {const spanElement = document.createElement('span');spanElement.textContent = `这是第 ${i + 1} 个<span>标签`;div.appendChild(spanElement);}observer.unobserve(lastSpanElement);lastSpanElement = div.querySelector('span:last-child');observer.observe(lastSpanElement)}}})observer.observe(lastSpanElement)</script>
</body></html>

详情可参考:(IntersectionObserver API详解_

IntersectionObserver 交叉观察器 - 简书 (jianshu.com)

IntersectionObserver

浏览器的5种观察器

app.directive

自定义全局指令,它有两种写法

// 注册(对象形式的指令)
// 所有生命周期都可
app.directive('my-directive', {/* 自定义指令钩子 */
})// 注册(函数形式的指令)
// 固定只在2个生命周期上触发, mounted 和 updated 
app.directive('my-directive', () => {/* ... */
})

 vue中install方法

可供我们开发新的自定义指令跟全局注册组件,第一个参数是vue的构造器,第二个参数是可选的选项对象

然后再开始编写扩展指令之图片懒加载指令

export default {install (app) {app.component(XtxSkeleton.name, XtxSkeleton)app.component(XtxCarousel.name, XtxCarousel)
+    defineDirective(app)}
}import defaultImg from '@/assets/images/200.png'
// 扩展指令
const defineDirective = (app) => {// 图片懒加载app.directive('lazyload', {mounted(el, binding) {const observer = new IntersectionObserver(([{ isIntersecting }]) => {if (isIntersecting) {// 停止观察observer.unobserve(el)el.onerror = () => {// 图片加载失败 设置默认图el.src = defaultImg}// binding 是对象,.value就是绑定指令的值el.src = binding.value}}, {//目标元素和根元素相交部分的比例达到该值的时候,//callback 函数将会被执行threshold: 0.01})// 开始观察observer.observe(el)}})
}

使用扩展的图片懒加载指令:

<img alt="" v-lazyload="goods.picture" />

扩展:

vue还有许多工具库,其中也有类似的api可以实现这种功能,列如:

useIntersectionObserver | VueUse

相关文章:

【懒加载】js实现懒加载、vue实现图片懒加载指令

懒加载 延迟加载&#xff0c;对于一个很长的页面&#xff0c;优先加载可视区域的内容&#xff0c;其他部分等进入可视区域时再加载 懒加载作用 是一种网页性能优化的方式&#xff0c;它能极大的提升用户体验。比如一个页面中有很多图片&#xff0c;但是首屏只出现几张&#…...

微信小程序教学系列(7)

第七章&#xff1a;小程序安全和权限管理 第一节&#xff1a;小程序安全性保障 在开发小程序时&#xff0c;我们要时刻牢记小程序的安全性。毕竟&#xff0c;我们可不希望我们的小程序被黑客入侵或者用户的隐私被泄露。所以&#xff0c;让我们一起来了解一下如何保障小程序的…...

Android 9.0 kenel和frameworks中修改ram运行内存的功能实现

1.前言 在9.0的系统rom产品开发定制中,在对一些产品开发中的配置需求方面,在产品后续订单中,在某些机型中需要升级下系统内核配置,项目时间比较仓促,所以 来不及对硬件重新定制,就需要软件方面在ram运行内存的容量大小方面作假,修改ram真实的大小容量,所以就需要在ken…...

PHP实践:获取网络上图片的长宽以及图片类型

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;2023年6月CSDN上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责…...

使用 DPO 微调 Llama 2

简介 基于人类反馈的强化学习 (Reinforcement Learning from Human Feedback&#xff0c;RLHF) 事实上已成为 GPT-4 或 Claude 等 LLM 训练的最后一步&#xff0c;它可以确保语言模型的输出符合人类在闲聊或安全性等方面的期望。然而&#xff0c;它也给 NLP 引入了一些 RL 相关…...

数据库——事务,事务隔离级别

文章目录 什么是事务?事务的特性(ACID)并发事务带来的问题事务隔离级别实际情况演示脏读(读未提交)避免脏读(读已提交)不可重复读可重复读防止幻读(可串行化) 什么是事务? 事务是逻辑上的一组操作&#xff0c;要么都执行&#xff0c;要么都不执行。 事务最经典也经常被拿出…...

对《VB.NET通过VB6 ActiveX DLL调用PowerBasic及FreeBasic动态库》的改进

《VB.NET通过VB6 ActiveX DLL调用PowerBasic及FreeBasic动态库》使用的Activex DLL公共对象是需要先注册的。https://blog.csdn.net/weixin_45707491/article/details/132437502?spm1001.2014.3001.5501 Activex DLL事前注册&#xff0c;一次多用说起来也不是啥大问题&#x…...

【PHP】数据类型运算符位运算

文章目录 数据类型简单&#xff08;基本&#xff09;数据类型&#xff1a;4个小类复合数据类型&#xff1a;2个小类特殊数据类型&#xff1a;2个小类类型转换类型判断整数类型浮点类型布尔类型 运算符赋值运算符算术运算符比较运算符逻辑运算符连接运算符错误抑制符三目运算符自…...

使用 Nacos 作为 Spring Boot 配置中心

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…...

微服务 Eureka

Eureka Eureka是Netflix开源的一个用于构建基于微服务架构的服务发现和注册中心技术。在微服务架构中&#xff0c;系统被拆分成多个小型、自治的服务&#xff0c;每个服务负责特定的业务功能。这些服务需要能够相互发现和通信&#xff0c;这就是Eureka所提供的功能。 Eureka主…...

Spring Boot 事务和事务传播机制

1. 为什么需要事务? 事务定义 将一组操作封装成一个执行单元 (封装到一起)&#xff0c;这一组的执行具备原子性, 那么就要么全部成功&#xff0c;要么全部失败. 为什么要用事务? 比如转账分为两个操作: 第一步操作:A 账户-100 元。 第二步操作:B账户 100 元。 如果没有事务&a…...

计算机组成原理(巨巨巨基础篇)

有关《计算机组成原理》课本中有关 内存计算换算&#xff08;字&#xff0c;位&#xff0c;字节&#xff09; 个人理解 前面知识点搭建框架&#xff0c;最后两道例题是直观理解体会 主存储器的基本概念 位&#xff1a;存储信息的最小单位&#xff0c;称为存储位或存储元。 背…...

C语言:选择+编程(每日一练Day7)

目录 选择题&#xff1a; 题一&#xff1a; 题二&#xff1a; 题三&#xff1a; 题四&#xff1a; 题五&#xff1a; 编程题&#xff1a; 题一&#xff1a;图片整理 思路一&#xff1a; 思路二&#xff1a; 题二&#xff1a;寻找数组的中心下标 思路一&#xff1…...

leetcode做题笔记93. 复原 IP 地址

有效 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 . 分隔。 例如&#xff1a;"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址&#xff0c;但是 "0.011.255.2…...

HTTPS 中间人攻击

HTTPS 中间人攻击 中间人攻击过程 通讯过程 客户端——中间人——服务器 过程如下 服务器向客户端发送公钥攻击者截获公钥&#xff0c;保留在自己手上然后攻击者自己生成一个【伪造的】公钥&#xff0c;发给客户端客户端收到【伪造的】公钥后&#xff0c;利用【伪造的】公…...

MATLAB打开excel读取写入操作例程

本文使用素材含代码测试用例等 MATLAB读写excel文件历程含&#xff0c;内含有测试代码资源-CSDN文库 打开文件 使用uigetfile函数过滤非xlsx文件&#xff0c;找到需要读取的文件&#xff0c;首先判断文件是否存在&#xff0c;如果文件不存在&#xff0c;程序直接返回&#x…...

[C语言]分支与循环

导言&#xff1a; 在人生中我们总会有选择&#xff0c;**如下一顿吃啥&#xff1f;**又或者每天都是在重复&#xff0c;吃饭&#xff01;&#xff01;&#xff01;&#xff01;&#xff0c;当然在C语言中也有选择和重复那就是分支语句与循环语句 文章目录 分支循环循环中的关键…...

绘制区块链之链:解码去中心化、安全性和透明性的奇迹

区块链技术以其去中心化、安全性和透明性等特点在全球范围内引起了广泛的关注和兴趣。区块链是一种分布式账本技术&#xff0c;通过将数据以不可篡改的方式链接在一起&#xff0c;创建了一个安全可靠的数据库。这种革命性的技术正在许多领域中发挥作用&#xff0c;包括加密货币…...

4G工业路由器的功能与选型!详解工作原理、关键参数、典型品牌

随着工业互联网的发展,4G工业路由器得到越来越广泛的应用。但是如何根据实际需求选择合适的4G工业路由器,是许多用户关心的问题。为此,本文将深入剖析4G工业路由器的工作原理、重要参数及选型要点,并推荐优质的品牌及产品,以提供选型参考。 一、4G工业路由器的工作原理 4G工业…...

c与c++中struct的主要区别和c++中的struct与class的主要区别

1、c和c中struct的主要区别 c中的struct不可以含有成员函数&#xff0c;而c中的struct可以。 C语言 c中struct 是一种用于组合多个不同数据类型的数据成员的方式。struct 声明中的成员默认是公共的&#xff0c;并且不支持成员函数、访问控制和继承等概念。C中的struct通常被用…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...