了解图片懒加载原理并实现简易版图片懒加载

444 阅读2分钟

「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战

为什么要做图片懒加载(lazyload)?

首先我们先来聊聊为啥要做图片懒加载,首先就是在众多网络资源中图片对网页性能的影响一直是大的。如果每次进入页面就请求所有的图片资源,那么可能等这些图片加载出来用户也早就走了。所以,我们需要懒加载,进入页面的时候,只请求可视区域的图片资源。

我们来简单总结一下:

  1. 一次性把全部图片都加载完毕会极大的延长网页加载时间,从而影响到用户的体验
  2. 有的时候用户不需要加载出所以的图片而一次性全部加载。

那么如果实现图片懒加载呢?

图片懒加载实现

项目环境搭建

  • 使用npm来初始化项目
npm init -y
  • 安装vite
npm i vite -D

编写页面骨架

  • 首先先写一个简单的页面骨架
<ul id="list"></ul>
  • 引入index.js文件
<script src="./index.js"></script>
  • 在index.js文件中实现一个简单的图片懒加载
;((document)=>{

    const oList = document.querySelector("#list")
    
    const init ()=>{}
    init ()
})(document)
  • 初始化时,将img的src设置成default.gif
const oList = document.querySelector("#list")

  function createLi(data){
    const oLi = document.createElement("li")
    oLi.innerHTML = `
     <img src="./image/default.gif" data-src="./image/img.jpg" />
    `
    return oLi
  }
  const init = ()=>{
    for(let i = 0; i<200;i++){
      oList.appendChild(createLi(i)) 
    }
  }
 init = () 
  • 从页面获取所有的图片。
let imgs = document.querySelectorAll('img[data-src]')

  • 遍历每个图片判断当前图片是否在可视区的范围内。

    imgs.forEach((item, index) => {
      if (item.dataset.src === '') return        
      const distance = viewHeight - item.getBoundingClientRect().top;
      if (distance>0) {
        item.src = item.dataset.src
        item.removeAttribute('data-src')
      }
    })

  • 如果到了就设置图片的 src 属性。

    imgs.forEach((item, index) => {
      if (item.dataset.src === '') return        
      const distance = viewHeight - item.getBoundingClientRect().top;
    })

  • 最后记着绑定 window 的 scroll 事件,对其进行事件监听。同时在页面加载完毕时也要调影响lazyload方法

window.addEventListener('scroll', lazyload)

这样一个简单的图片懒加载就已经完毕了,但是还是有一个比较大的问题就是scroll事件触发太多了,我们应该使用节流来优化一下。

使用防抖函数优化项目

  • 定义一个debounce函数
function debounce(fn, delay = 500, ...args) {
  let timer = null;
  // 这里的e是event事件对象
  return function (e) {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(this, args);
    }, delay);
  };
}
  • 将事件监听scroll改造一下
window.addEventListener('scroll', debounce(lazyload, 200))