LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

前端性能优化-图片的预加载和懒加载

admin
2024年11月22日 14:35 本文热度 602

本文转载于稀土掘金技术社区,作者:hy_花花

原文链接:https://juejin.cn/post/7406279925119303714

前言

在说到对图片资源进行优化时,那就不得不提到图片预加载和图片懒加载,可能很多朋友都了解这两者,但是一直没有很清晰的概念,以及什么时候用,用在什么场景下,今天就来详细的了解一下吧!

图片的预加载

  1. 什么是预加载?
  • 预加载就是提前加载需要用到的图片素材,在用户需要用的时候可以直接从本地缓存中获取并渲染。
  1. 预加载的原理
  • 提前加载所需要的图片资源,加载完毕后会缓存到本地,当需要时可以立马显示出来,以达到在预览的过程中,无需等待直接预览的良好体验。简而言之,就是需要显示前先加载。
  1. 为什么要使用预加载
  • 原因是,在网页全部加载之前,对一些主要内容进行加载,以提供给用户更好的体验,减少等待的时间。否则,如果一个页面的内容过于庞大,没有使用预加载技术的页面就会长时间的展现为一片空白,直到所有内容加载完毕。

预加载的实现方式

  1. css的方式
<div class="preload-pic"></div>
.preload-pic { background: url(https://img2.baidu.com/it/u=1028011339,1319212411&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=313) no-repeat }  
  1. 使用js实现,通过new Image对象设置实例对象的src属性实现图片的预加载。

    • 代码实现:
 <div class="img-container">
  <p></p>
  <img src="../../static/1.jpg" alt="图片" id="img" />
</div>
<script>
  const imgList = [
    '../../static/2.jpg',
    '../../static/3.jpg',
    '../../static/4.jpg',
    '../../static/5.jpg',
    '../../static/6.jpg',
    '../../static/7.jpg',
    '../../static/8.jpg',
    '../../static/9.jpg'
  ]

  /
/ 当前图片下标
  let current = 0
  const getImage = document.getElementById('img')
  const p = document.querySelector('p')
  p.innerHTML = `实现预加载的效果,我是第${current + 1}张图片`
  
  /
/页面一开始加载数组的第一个元素
  preLoad(imgList[current]).then(data => {
    console.log(data)
  })

    /
/ 预加载函数
    function preLoad(src) {
    return new Promise((resolve, reject) => {
      /
/ 创建一个新的图片标签
      const image = new Image()
        /
/ 将传进来的src赋值给新的图片
        image.src = src
      /
/ 图片加载完成调用成功状态
      image.addEventListener('load', () => resolve(image), false)
      /
/ 图片加载完成调用失败状态
      image.addEventListener('error', () => reject(), false)
      
    })
  }

  getImage.addEventListener('click', () => {
    /
/ 当索引小于数组的长度时
    if (current < imgList.length) {
      /
/ 将数组元素的src赋值给页面的元素
      getImage.src = imgList[current]
      /
/ 当前递增值加1,下次点击变成数组的第二个元素
      current++
      p.innerHTML = `实现预加载的效果,我是第${current + 1}张图片`

      /
/切换图片后,同时让浏览器提前加载下一张图片
      if (current < imgList.length) {
        preLoad(imgList[current]).then(data => {
          console.log('预加载成功', data)
        })
      }
    } 
  })
</
script>

图片的懒加载

  1. 什么事懒加载?
  • 懒加载其实也叫做延迟加载、按需加载,在比较长的网页或应用中,如果图片有很多,一下子之间把所有的图片都加载出来的话,耗费很多性能,而且用户不一定会把图片全部看完。只有当图片出现在浏览器的可视区域内时,让图片显示出来,这就是图片懒加载。
  1. 懒加载的原理
  • 懒加载其实也叫做延迟加载、按需加载,在比较长的网页或应用中,如果图片有很多,一下子之间把所有的图片都加载出来的话,耗费很多性能,而且用户不一定会把图片全部看完。只有当图片出现在浏览器的可视区域内时,让图片显示出来,这就是图片懒加载。
  1. 为什么使用懒加载
  • 当页面很多,内容很丰富的时候,页面很长,图片较多,比如淘宝页面,要是页面载入就一次性加载完毕,就需要等很长的时间。

懒加载的实现方式

  1. 实现方式一

    • getBoundingClientRect方法
    • 参考文档:developer.mozilla.org/zh-CN/docs/…[1]
 <div class="img-box">
      <div class="img-container">
        <img
          src="https://gitee.com/z1725163126/cloundImg/raw/master/loading.gif"
          alt=""
          data-src="../../static/1.jpg"
          class="lazyload"
        />

      </div>

      <div class="img-container">
        <img
          src="https://gitee.com/z1725163126/cloundImg/raw/master/loading.gif"
          alt=""
          data-src="../../static/2.jpg"
          class="lazyload"
        />

      </div>

      <div class="img-container">
        <img
          src="https://gitee.com/z1725163126/cloundImg/raw/master/loading.gif"
          alt=""
          data-src="../../static/3.jpg"
          class="lazyload"
        />

      </div>

    </div>
  <script>
      const getImage = [...document.querySelectorAll('.lazyload')]
      function lazyLoad() {
        getImage.forEach(item => {
          /
/ 判断是否在可视区域内
          if (isInVisible(item)) {
          /
/ 如果在可视区域内,就设置src的路径
            item.src = item.dataset.src
          }
        })
      }

      function isInVisible(image) {
        const rect = image.getBoundingClientRect()
        return (
          rect.bottom > 0 &&
          rect.top < window.innerHeight &&
          rect.right > 0 &&
          rect.left < window.innerWidth
        )
      }
      lazyLoad()
     /
/ window.addEventListener('scroll', lazyLoad)
      
      /
*
        优化:
        节流 :事件处理函数执行一次后,在某个时间期限内不再工作
        fun:传入一个函数
        miliseconds:间隔时间
      */

      function throttle(fun, time = 250) {
        let lastTime = 0 /
/最后一次执行的时间
        return function (...args) {
          const now = new Date().getTime()
          if (now - lastTime >= time) {
            fun()
            lastTime = now
          }
        }
      }
      window.addEventListener('scroll', throttle(lazyLoad, 1000), false)
    </
script>
  1. 实现方式二

    • 使用IntersectionObserver API 交叉视口
    • 参考文档:developer.mozilla.org/zh-CN/docs/…[2]
<script>
      // 转换成数组方便处理
      const imgList = [...document.querySelectorAll('.lazyload')]

      // 实例化构造函数
      const observer = new IntersectionObserver(entries => {
        //entries是一个数组,所以还需要遍历
        console.log(entries)
        entries.forEach(item => {
          //isIntersecting是否在可视区域展示
          if (item.isIntersecting) {
            //获取图片的自定义属性并赋值给src
            item.target.src = item.target.dataset.src
            //替换为真是src地址后取消对它的观察
            observer.unobserve(item.target)
          }
        })
      })

      //遍历所有的图片,给每个图片添加观察
      imgList.forEach(item =>  observer.observe(item))
      
    </script>
  1. 实现方式三

    • VueUse中useIntersectionObserver
    • 参考文档:vueuse.nodejs.cn/core/useInt…[3]
// 使用自定义指令
<template>
  <div class="laz-box" v-for="item in imgList" :key="item.id">
    <img v-img-lazy="item.url" style="width: 100vw; height: 200px" />
  </div>

</template>

<script setup>
import { reactive } from 'vue'
const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15].map(i => {
  return {
    id: `${i}`,
    url: require(`../
static/${i}.jpg`)
  }
})
const imgList = reactive(data)
</script>

注册全局自定义指令:
import { useIntersectionObserver } from '@vueuse/core'
export const lazyPlugin = {
  install(app) {
    app.directive('img-lazy', {
      mounted(el, binding) {
        // el: 指令挂载到的那个元素 dom 的 img
        // binding: value 指令等于号后面表达式的值 url
        el.src = require(`
../static/loading.gif`)
        const { stop } = useIntersectionObserver(el, ([{ isIntersecting }]) => {
          console.log('进入可视区域', isIntersecting)
          //判断当前监听元素是否进入视口区域
          if (isIntersecting) {
            el.src = binding.value
            el.onerror = () => {
              el.src = require(`
../static/loading.gif`)
            }
            // 加载图片之后停止监听
            stop()
          }
        },
        {
          threshold: 0.5
        }
      )
      }
    })
  }
}

两者的区别

二者都是提高页面性能的有效办法,区别是一个是提前加载,一个是延迟加载甚至不加载.

  • 懒加载对服务器前端有一定的缓解压力的作用.
  • 预加载则会增加服务器前端的压力,换取更好的用户体验,这样可以使用户的操作得到最快的反映。


该文章在 2024/11/22 16:02:00 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2024 ClickSun All Rights Reserved