实现图片懒加载的5种方式

news2025/1/11 18:33:41

目录

1、懒加载介绍

2、实现懒加载技术的方案

3、具体实现代码


1、懒加载介绍

当页面需要展示大量图片时,如果一次性渲染所有图片,会向服务器发出大量请求,导致服务器响应慢,出现页面卡顿或崩溃等问题。用懒加载技术只预先加载可视区内的图片,当滚动到其他位置时,才去加载这块区域的图片,也可以使用比较小的loading图片进行占位,有效减轻服务器的压力,加速页面渲染,提高用户体验。

2、实现懒加载技术的方案

(1)使用element-ui 的<el-image v-for="url in urls" :key="url" :src="url" lazy></el-iamge>可通过lazy开启懒加载功能,当图片滚动到可视范围内才会加载。

(2)使用vue-lazyLoad插件实现

(3)使用IntersectionObserver Api监听某些节点是否出现在可视区域内。

(4)offsetTop(图像距离顶部的高度)-scrollTop(页面被卷去的高度)<=window.innerHeight(可视区高度)才加载

(5)获得页面中某个元素的上边相对浏览器视窗的位置getBoundingClientRect().top<=window.innerHeight(可视区高度)才加载

3、具体实现代码

(1)element-ui <el-image> Element - The world's most popular Vue UI framework

(2)使用vue-lazyLoad插件实现,安装【npm i vue-lazyload -S】,main.ts中进行注册

//main.ts
import VueLazyload from 'vue-lazyload'
app.use(VueLazyload,
    {preLoad: 1.3, //预加载的宽高比loading: 
    loadimage:"./assets/vue.svg", //图片加载状态下显示的图片
    // error: "", //图片加载失败时显示的图片
    attempt: 1, // 加载错误后最大尝试次数
})

页面中通过v-lazy使用

//xx.vue
<template>
  <div>
    <div v-for="item in arr" :key="item">
      <img v-lazy="item" width="600" height="200" alt="" />
    </div>
  </div>
</template>

<script lang="ts" setup>
//glob是懒加载模式,globEager静态加载
let imageList: Record<string, { default: string }> = import.meta.glob(
  "../assets/images/*.*",
  { eager: true }
);
let arr = Object.values(imageList).map((v) => v.default);
</script>

<style lang="scss" scoped></style>
使用vite的两种文件导入方式
  • 【import.meta.glob("/xx")】方式 为懒加载模式,动态导入,构建时,会分离为独立的 chunk,该方式导入使用()=>import("/xx"),跟路由懒加载是一样的导入方式。
  • 【import.meta.globEager("/xx")】以及【import.meta.glob("/xx",{eager:true})】为静态加载

 打印imageList如图

 (3)使用IntersectionObserver Api监听某些节点是否出现在可视区域内。

intersectionRatio表示节点出现在可视区的比例,isIntersecting为布尔值,为true表示出现在可视区

<template>
  <div>
    <div v-for="item in arr" :key="item">
      <img v-lazy="item" width="600" height="200" alt="" />
    </div>
  </div>
</template>

<script lang="ts" setup>
import type { Directive } from "vue";
//glob是懒加载模式,globEager静态加载
let imageList: Record<string, { default: string }> = import.meta.glob(
  "../assets/images/*.*",
  { eager: true }
);
console.log(">>>>>>>>>>>>>>>imageList", imageList);
let arr = Object.values(imageList).map((v) => v.default);
console.log(arr);
// 使用自定义指令
let vLazy: Directive<HTMLImageElement, string> = async (el, bingding) => {
  let url = await import("../assets/vue.svg");
  el.src = url.default;
  let observer = new IntersectionObserver((entry) => {
    console.log(entry[0], el);
    if (entry[0].intersectionRatio > 0 && entry[0].isIntersecting) {
      el.src = bingding.value;
      observer.unobserve(el);//停止监听el对象
    }
  });
  observer.observe(el); //开启监听el对象
};
</script>

<style lang="scss" scoped></style>

(4)判断图像的offsetTop(距离顶部的高度)-scrollTop(页面被卷去的高度)<=window.innerHeight(可视区高度)才加载

<template>
  <div>
    <div v-for="item in arr" :key="item">
      <img
        ref="img"
        :data-src="item"
        src="../assets/vue.svg"
        width="600"
        height="200"
        alt=""
      />
    </div>
  </div>
</template>

<script lang="ts" setup>
import { onMounted } from "vue";

//glob是懒加载模式,globEager静态加载
let imageList: Record<string, { default: string }> = import.meta.glob(
  "../assets/images/*.*",
  { eager: true }
);
let arr = Object.values(imageList).map((v) => v.default);
const winHeight = window.innerHeight; // 浏览器可视区的高度

onMounted(() => {
  var imgs = document.querySelectorAll("img");
  let num = Math.ceil(winHeight / 200);
  loadImg(imgs, 0, num); //   1.只加载可视区域内的图片-适用于图片高度固定的场景
  window.addEventListener("scroll", function () {
    loadImg(imgs, num, imgs.length); // 2.滚动时加载其他未加载的图片
  });
});
function loadImg(img, startIdx, num) {
  for (let i = startIdx; i < num; i++) {
    if (startIdx == 0) {
      img[i].src = img[i].dataset.src;
    } else {
      var imgOffsetTop = img[i].offsetTop; // 图片距顶部的高度
      var scrollTop = document.documentElement.scrollTop; // 页面被卷去的高度
      if (imgOffsetTop - scrollTop <= winHeight) {
        // 判断图片是否将要出现
        img[i].src = img[i].dataset.src; // 出现后将自定义地址转为真实地址
      }
    }
  }
}
</script>

(5)获得页面中某个元素的上边相对浏览器视窗的位置getBoundingClientRect().top<=window.innerHeight(可视区高度)才加载

<template>
  <div>
    <div v-for="item in arr" :key="item">
      <img
        ref="img"
        :data-src="item"
        src="../assets/vue.svg"
        width="600"
        height="200"
        alt=""
      />
    </div>
  </div>
</template>

<script lang="ts" setup>
import { onMounted, ref } from "vue";
let timer = ref<number>(0);
//glob是懒加载模式,globEager静态加载
let imageList: Record<string, { default: string }> = import.meta.glob(
  "../assets/images/*.*",
  { eager: true }
);
console.log(imageList);

let arr = Object.values(imageList).map((v) => v.default);
const winHeight = window.innerHeight; // 浏览器可视区的高度

onMounted(() => {
  var imgs = document.querySelectorAll("img");
  let num = Math.ceil(winHeight / 200);
  loadImg(imgs, 0, num); //   1.只加载可视区域内的图片-适用于图片高度固定的场景
  window.addEventListener("scroll", (e) => {
    loadImg(imgs, num, imgs.length); // 2.滚动时加载其他未加载的图片
  });
});

function loadImg(img, startIdx, num) {
  for (let i = startIdx; i < num; i++) {
    if (startIdx == 0) {
      img[i].src = img[i].dataset.src;
    } else {
      const rect = img[i].getBoundingClientRect(); //getBoundingClientRect()用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置。
      if (rect.top < window.innerHeight) {
        img[i].src = img[i].dataset.src;
      }
    }
  }
}
</script>

注意:获取元素节点要放在onMounted钩子中,因此此时Dom才挂载完成

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

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

相关文章

渗透测试 | 指纹识别

0x00 免责声明 本文仅限于学习讨论与技术知识的分享&#xff0c;不得违反当地国家的法律法规。对于传播、利用文章中提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;本文作者不为此承担任何责任&#xff0c;一旦造成后果请自行承担…

LC-3中断实验

一、实验目的 学会分析和理解给定的编程问题&#xff1b;掌握中断驱动的基本原理&#xff1b;掌握键盘数据寄存器&#xff08;KBDR)及键盘状态寄存器&#xff08;KBSR&#xff09;工作基本原理&#xff1b;掌握输出数据寄存器&#xff08;DDR)及输出状态寄存器&#xff08;DSR…

Splunk安装配置

前言 Splunk 社区 &#xff0c;包括白皮书&#xff0c;各类手册&#xff0c;资源下载&#xff0c;社区问答等 入门&#xff1a;Splunk 入门指南 | Splunk 手册&#xff1a;Splunk Enterprise - Splunk Documentation 资源下载:数据可视化工具Splunk Enterprise免费下载 | S…

chatgpt赋能python:Python对Word文档的支持——打造高效办公新选择

Python对Word文档的支持——打造高效办公新选择 在现代社会&#xff0c;文档处理和管理已成为各行各业不可或缺的一部分。在这个领域中&#xff0c;Word文档一直占据主导地位&#xff0c;成为了几乎所有企业和机构必备的工具。而Python作为一门众所周知的高效编程语言&#xf…

雅思口语话题准备(一)

目录 where are you from&#xff1f; 3.Will you live in the countryside in the future? 4.Have you learned the history of your hometown at school? Does your name have any particular(or special)meaning? 作为一个英语音标大师&#xff0c;请问ɒ和ɔ他们之间有…

chatgpt赋能python:Python%(.2f)怎么用?从入门到进阶

Python%(.2f)怎么用&#xff1f;从入门到进阶 Python作为一种高效的编程语言&#xff0c;拥有广泛的应用领域&#xff0c;尤其在AI、数据分析、Web开发以及自动化运维等方面得到了广泛的应用&#xff0c;成为当下最受欢迎的编程语言之一。在这篇SEO文章中&#xff0c;我们将介…

5月25日第壹简报,星期四,农历四月初七

5月25日第壹简报&#xff0c;星期四&#xff0c;农历四月初七坚持阅读&#xff0c;静待花开1. 教育部&#xff1a;2023年为中西部乡镇卫生院培养订单定向免费五年制本科医学生共计6150人。2. 全球第一个集成人工智能功能的PC系统诞生&#xff01;微软宣布将在6月推出Windows Co…

c++ ffmpeg 浅谈YUV444、YUV422、YUV420(2)

本期将会给大家介绍YUV相关基础知识&#xff0c;同时也介绍威创网络分布式系统的卓越色彩处理技术。 1.什么是YUV色彩空间 2.YUV采样格式 3.YUV不同采样格式对图像画质的影响分析 一、什么是YUV色彩空间? YUV是视频、图片、相机等应用中常常使用的一类图像格式&#xff0c;是…

达美乐面试(部分)(未完全解析)

Java如何保证非线程安全的数据结构&#xff08;比如HashMap&#xff09;的原子性&#xff1f;读多写少时用哪种锁好? A: 方法1&#xff1a;CAS等乐观锁机制&#xff0c;方法2&#xff1a;如果读多写少&#xff0c;可以使用读写锁&#xff08;ReentrantReadWriteLock&#xff0…

【MySQL 数据库】3、多表查询

目录 一、多表关系二、多表查询三、内连接四、外连接五、自连接六、联合查询七、什么是子查询八、标量子查询九、列子查询十、行子查询十一、表子查询十二、多表查询练习题 一、多表关系 项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块…

移动端H5页面PDF操作及预览

环境&#xff1a;nodejs 适配&#xff1a;移动端主流浏览器支持企业微信低版本 插件&#xff1a;pdfjs-dist 2.6.347 方案一 本地构建 拉取项目&#xff1a; git clone https://github.com/mozilla/pdfjs-dist.git 全局安装gulp npm install -g gulp-cli 安装项目依赖 np…

chatgpt赋能python:Python中的s.len()方法介绍

Python中的s.len()方法介绍 Python中有各种字符串处理方法&#xff0c;其中s.len()方法是一个重要的方法之一。s.len()返回一个字符串s的长度。这是一个非常基本的方法&#xff0c;但是在很多情况下都会被使用。本文将介绍Python中s.len()方法的一些用法和注意事项。 s.len()…

Redis持久化及集群

Redis可以通过将数据保存在磁盘里实现持久化功能, 以防止宕机导致的数据大量丢失.但是持久化只能保证在磁盘不损坏的情况下, 长时间保存数据, 如果一旦磁盘损坏, 数据仍然会丢失. 为了解决这个问题, 主从复制应允而生. 主从复制是Redis集群中的一总, 其中一个Redis做主, 其他R…

C++数据结构:线性顺序表(数组)

文章目录 前言一、vector简介二、泛型编程自定义数组结构1、定义类2、删除、读取元素和首尾指针3、修改元素、获取元素数量、和插入 总结 前言 将一个线性表存储到计算机中&#xff0c;把线性表的结点按逻辑顺序依次存放到一组地址连续的存储单元里&#xff0c;用这种方法存储…

nodejs+vue+elementui个人心情日志博客网站系统5ht83

语言 node.js 框架&#xff1a;Express 前端:Vue.js 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat 开发软件&#xff1a;VScode 前端vueelementui,博客管理系统模块 该模块是博客管理系统中的重要模块&#xff0c;它也是博客管理系统的主模块&#xff0c;该模块的…

从 WebKit 看浏览器内核架构

浏览器常见的浏览器内核有&#xff1a;Blink、WebKit、Gecko、Trident 等&#xff0c;目前 WebKit 内核占据了非常大的的市场&#xff0c;包括 Chrome、Safari、安卓浏览器等市面上的主流浏览器&#xff0c;都使用了 WebKit 内核。 从 WebKit 看浏览器内核架构 既然 WebKit 这么…

lwip的arp协议的意义和更新时机

ARP协议存在的目的 ARP&#xff08;Address Resolution Protocol&#xff09;协议是 TCP/IP 协议族中的一个协议&#xff0c;它的主要目的是将 IP 地址解析为 MAC&#xff08;Media Access Control&#xff09;地址&#xff0c;以便在局域网中进行通信。 具体而言&#xff0c…

## 如何顺序处理设备上报的数据

1. 引言 随着智能技术的发展&#xff0c;市场上出现了很多的智能设备&#xff0c;其具有连接网络的能力。用户可以实现远程控制&#xff0c;并且设备也可上报自己的状态&#xff0c;实现云端对设备的运行情况分析。在某些情况下需要保证设备上报状态的有序性&#xff0c;例如传…

Unity之ShaderGraph 节点介绍 Input输入节点

目录 Input&#xff08;输入&#xff09;  1、Basic&#xff08;基本&#xff09;   1) Boolean&#xff08;布尔&#xff09;   2) Color&#xff08;颜色&#xff09;   3) Constant&#xff08;常量&#xff09;   4) Integer&#xff08;整型&#xff09;   5)…