vue 实现图片懒加载

这篇具有很好参考价值的文章主要介绍了vue 实现图片懒加载。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一:懒加载的目的

有些页面可能展示的是大量的图片,如果我们一次性加载所有图片就会浪费性能,影响用户体验,所以我们就会懒加载这些图片。即可视区域之外的图片不加载,随着页面的滚动,图片进入可视区域,则触发图片的加载显示。
优点:页面加载速度快,用户体验感更好且节省流量

二:懒加载的原理

  1. 存储图片的真实路径,把图片的真实路径绑定给一个以data开头的自定义属性data-src即可,页面中的img元素,如果没有src属性,浏览器就不会发出请求去下载图片(没有请求就提高了性能)
<img  data-src="xxx" src="xxx" width="180" height="180"/> 
  1. 需要一个滚动事件,判断元素是否在浏览器窗口,一旦进入视口才进行加载,当滚动加载的时候,就把这张图片替换为真正的url地址(也就是data-src里保存的值)
  2. 等到图片进入视口后,利用js提取data-src的真实图片地址赋值给src属性,就会去发送请求加载图片,真正实现了按需加载

实现图片懒加载的多种方法的区别就在于判断元素是否进入视口的方式不同,当使用方法3和方法4时,如果发生滚动事件,会产生大量的循环和判断操作判断图片是否可视区里,因此需要用节流进行优化。

三、 实现懒加载

方法1 lazyload插件

vue2

github地址
原理
vue-lazyload的核心原理是利用了IntersectionObserver API,这是一个用于检测元素是否与视口相交的API,它可以高效地监听元素的可见性变化,并触发回调函数。
vue-lazyload在注册插件时,会创建一个全局的IntersectionObserver实例,并设置一些选项,如阈值(threshold)、根元素(root)等。然后,在绑定v-lazy指令时,会创建一个监听器(listener)对象,并将其添加到一个监听器队列(listenerQueue)中。每个监听器对象都包含了元素的相关信息,如状态(state)、图片地址(src)等。
接下来,vue-lazyload会遍历监听器队列,并调用IntersectionObserver实例的observe方法,将每个元素注册到观察者中。当元素与视口相交时,IntersectionObserver实例会触发回调函数,并传入一个entries参数,表示所有被观察的元素的状态信息。vue-lazyload会根据entries中的isIntersecting属性判断元素是否可见,如果是,则调用监听器对象的load方法,将元素的src或者style属性替换为真实的图片地址,并将该监听器对象从队列中移除。
基本用法

  1. 安装
npm i vue-lazyload@1.2.3 -S
  1. 使用
    main.ts
// 1.图片懒加载插件
import VueLazyload from 'vue-lazyload'

// 2.注册插件
Vue.use(VueLazyload, {
  //参数配置 可不填
  
  // 懒加载默认加载图片
  loading: 'xxx.png',
  // 加载失败后加载的图片
  error: 'xxx.png',
  preLoad: 1.3, // 预加载高度的比例
  attempt: 3 // 尝试加载次数
})

可选参数配置项
vue 实现图片懒加载,vue.js,javascript,ecmascript

vue-lazyload提供了一个自定义指令v-lazy,可以在img标签或者任何需要设置背景图片的标签上使用它。例如:

<!-- 懒加载img标签 -->
<img v-lazy="imgUrl" />

<!-- 懒加载背景图片 -->
<div v-lazy:background-image="bgUrl"></div>

v-lazy指令接收一个字符串类型的值,表示图片的地址。如果是背景图片,需要在指令后加上:background-image修饰符。
当页面滚动时,vue-lazyload会检测元素是否进入可视区域,如果是,则替换元素的src或者style属性,从而实现懒加载。
⚠️ 若图片为循环渲染、分页显示,则必须写key值,不然切换页面后页面视图不刷新

vue3

github地址
原理与使用方法与vue2版本插件相同,仅安装不同

  1. 安装
npm i vue-lazyload-next -S
  1. 使用
    main.ts
import VueLazyloadNext from 'vue-lazyload-next';

app.use(VueLazyloadNext, {
  // 添加一些配置参数 可不填
  
  // 懒加载默认加载图片
  loading: 'xxx.png',
  // 加载失败后加载的图片
  error: 'xxx.png',
  preLoad: 1.3, // 预加载高度的比例
  attempt: 3 // 尝试加载次数
});

这个插件支持背景图;且图片不会反复加载【加载过的不会再加载】;

方法2 IntersectionObserve()

API
原理
Intersection Observer是是浏览器原生提供的构造函数,使用它能省到大量的循环和判断。这个构造函数的作用是它能够观察可视窗口与目标元素产生的交叉区域。简单来说就是当用它观察我们的图片时,当图片出现或者消失在可视窗口,它都能知道并且会执行一个特殊的回调函数,就可以利用这个回调函数实现需要的操作。
hook
vue3中选择用hook进行集成
useLazyload.ts文件

// 定义自定义指令
const defineDirective = (app: any) => {
  app.directive('lazy', {
    mounted(el: HTMLImageElement, bindings: any) {
      // el表示使用指令的DOM元素
      // 指令的功能:实现图片的懒加载
      // 1、监听图片是否进入可视区
      const observer = new IntersectionObserver(([{ isIntersecting }]) => {
        // true;进入可视区域,false:未进入可视区域
        if (isIntersecting) {
          // 1、给图片的src属性赋值图片的地址
          el.src = bindings.value;
          // 2、取消图片的监听,默认是会一直监听的,如果不取消。就会一直执行
          // eslint-disable-next-line spellcheck/spell-checker
          observer.unobserve(el);
        }
      });
      // 监听dom元素
      observer.observe(el);
    }
  });
};
export default {
  install(app: any) {
    // 自定义指令
    defineDirective(app);
  }
};

基本用法
main.ts

import lazy from './hooks/useLazy';

app.use(lazy);

对需要进行懒加载的img标签,直接将:src替换为v-lazy

   <img
      class="image"
      :key="data.rendered_result_image_url"
      v-lazy="data.rendered_result_image_url"
    />

⚠️若图片为循环渲染、分页显示,则必须写key值,不然切换页面后页面视图不刷新

方法3 loading="lazy

HTML新增 loading属性
基本用法

<img src="xxx.png" loading="lazy">

loading 属性支持 3 种属性值:

  • auto 浏览器默认的懒加载策略,和不增加这个属性的表现一样
  • lazy 在资源距当前视窗到了特定距离内后再开始加载
  • eager 立即加载,无论资源在页面中什么位置

图片必须声明width和height,不然会看到布局发生移动
兼容性
vue 实现图片懒加载,vue.js,javascript,ecmascript

不适用于背景图情况;

方法4 滚动监听+scrollTop+offsetTop+innerHeight

如何判断元素是否到达可视区域

  • window.innerHeight 是浏览器可视区的高度;
  • document.body.scrollTop || document.documentElement.scrollTop是浏览器滚动的过的距离;
  • imgs.offsetTop 是元素顶部距离文档顶部的高度(包括滚动条的距离);
  • 内容达到显示区域: img.offsetTop < window.innerHeight + document.body.scrollTop;
  • 到达可视区域后,imgs[i].src = imgs[i].getAttribute('data-src') as string; 将data-src属性值赋值给src,实现懒加载
    (在我项目中:)
    !!!!但在集成过程中发现,由于img父元素标签没有设置高度,scrollTop始终为0,无法实现动态计算window.innerHeight + document.body.scrollTop的值【一体化-算法版本-标准图】;不适用于没有设置父级高度的情况

方法5 滚动监听+getBoundingClientRect()

API

//获取所有img标签
const imgs = document.getElementsByTagName('img');

onMounted(() => {
   //用于首屏加载
  lazyLoad();
  //添加滚动事件监听
  document.addEventListener('scroll', throttle(lazyLoad, 500), true);
});
onUnMounted(() => {
  document.removeEventListener('scroll', throttle(lazyLoad, 500), true);
});

// 节流
const throttle = (fn: { apply: (arg0: any, arg1: any[]) => void }, t: number) => {
  let flag = true;
  const interval = t || 500;
  return function (this: any, ...args: any) {
    if (flag) {
      fn.apply(this, args);
      flag = false;
      setTimeout(() => {
        flag = true;
      }, interval);
    }
  };
};

const lazyLoad = () => {
  const offsetHeight = window.innerHeight || document.documentElement.clientHeight;
  Array.from(imgs).forEach(item => {
    const oBounding = item.getBoundingClientRect(); //返回一个矩形对象,包含上下左右的偏移值
    if (0 <= oBounding.top && oBounding.top <= offsetHeight) {
      //     //性能优化 进行判断 已经加载的不会再进行加载
      if (item.getAttribute('alt') !== 'loaded') {
        item.setAttribute('src', item.getAttribute('data-src') as string);
        item.setAttribute('alt', 'loaded');
      }
    }
  });
};

缺点文章来源地址https://www.toymoban.com/news/detail-653685.html

  • 挂载时需要立刻调用lazyLoad函数,不然首屏不会加载;若需要图片分页,切换分页后不会也主动加载,需要调用lazyLoad方法
  • 同样需要给图片设置key值,不然分页图片不刷新
  • 写在image组件内部的话会反复调用lazyload方法,需要写在外层组件

到了这里,关于vue 实现图片懒加载的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Vue.js 中使用 Element UI 实现异步加载分页列表

    在前端开发中,我们常常需要展示大量数据,并提供分页浏览的功能。本篇博客将介绍如何使用 Vue.js 和 Element UI 组件库创建一个简单的异步加载分页列表。 Vue.js Element UI JavaScript 我们将创建一个包含表格和分页组件的 Vue 单文件组件。以下是组件的基本结构: 引入 Element U

    2024年02月04日
    浏览(58)
  • Node.js: express + MySQL + Vue实现图片上传

            前段时间用Node.js: express + MySQL + Vue + element组件做了一个小项目,记录一下图片上传的实现。         将图片存入数据库有两种方法:                 1,将图片以二进制流的方式存入数据库(数据库搬家容易,比较安全,但数据库空间的消耗大,访问会比较缓慢)

    2024年02月07日
    浏览(99)
  • vue3+vant+cropper.js实现移动端图片裁剪功能

    最近做项目中遇到一个需求,需要对海报图片按照一定的比例进行裁剪并上传到oss。一开始这个需求思路有两个,使用canvas原生或者寻找现成的第三方库,对比了一番觉得canvas实现时间耗费较长,且秉承着不重复造轮子的原则(其实是菜)。 在进行技术调研后,决定使用vu

    2024年02月01日
    浏览(46)
  • 3分钟搞懂:JavaScript 和 ECMAScript

    ECMAScript 是 JavaScript 语言的 国际标准 ,JavaScript 是 ECMAScript 的 一种实现 (Adobe ActionScript 和 JScript 同样实现了 ECMAScript)。 ECMAScript 是欧洲计算机制造商协会 ECMA(European Computer Manufacturers Association)发布的浏览器脚本语言标准。它是 262 号标准文件,又叫 ECMA-262。 ECMAScript 定义

    2023年04月22日
    浏览(47)
  • 前端学习笔记:JavaScript基础语法(ECMAScript)

    此博客参考b站:【黑马程序员前端JavaScript入门到精通全套视频教程,javascript核心进阶ES6语法、API、js高级等基础知识和实战教程】https://www.bilibili.com/video/BV1Y84y1L7Nn?p=76vd_source=06e5549bf018e111f4275c259292d0da 这份笔记适用于已经学过一门编程语言(最好是C语言)的同学,如果你没有

    2024年02月16日
    浏览(47)
  • Three.js加载360全景图片/视频

    效果 原理 将全景图片/视频作为texture引入到three.js场景中 将贴图与球形网格模型融合,将球模型当做成环境容器使用 处理视频时需要以dom为载体,加载与控制视频动作 每次渲染时更新当前texture,以达到视频播放效果 全景图片加载有球体与正方体两种模式,区别在于是加载

    2024年02月04日
    浏览(42)
  • js,jquery解决 图片加载-滚动底部 问题

    问题描述 :让图片加载完成后,再执行滚动函数,避免出现图片加载一半的时候,滚动下来底部只出现半张图片。 这里记录4种测试成功方式: (适用于不容易找到图片位置的情况,否则直接onload函数即可)

    2024年01月18日
    浏览(36)
  • 使用JavaScript和Vue.js框架开发的电子商务网站,实现商品展示和购物车功能

    引言: 随着互联网的快速发展和智能手机的普及,电子商务行业正迎来一个全新的时代。越来越多的消费者选择网上购物,而不再局限于传统的实体店。这种趋势不仅仅是改变了消费者的习惯购物,也给企业带来了巨大的商机。为了不断满足消费者的需求,电子商务网站需要

    2024年02月15日
    浏览(59)
  • 直接在html中引入Vue.js的cdn来实现一个简单的上传图片组件

    当使用 Vue.js 的 CDN 来实现一个简单的上传图片组件时,你可以利用 Vue 的数据绑定和事件处理能力,结合 HTML 和 CSS,轻松地创建一个交互式的图片上传界面。以下是一个示例: index.html TANKING https://afdian.net/item/ffa3292a337c11ee9a8c5254001e7c00

    2024年02月13日
    浏览(44)
  • 深入理解 ECMAScript modules:提升你的 JavaScript 技能(六)

    🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_ CSDN 博客专家、23年度博客之星前端领域TOP1 🕠 牛客 高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课 签约作者、上架课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你

    2024年02月21日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包