JS实现图片的懒加载

为什么使用图片懒加载

当一个网站有很多图片资源时,如果一起加载会使网页加载很慢,影响用户体验,而且服务器的压力也会很大。

懒加载的原理是什么

img标签如果没有src属性,浏览器就不回去发送请求下载图片,只有当通过JavaScript设置了src属性后,浏览器才会发送请求下载图片。我们可以通过"data-*"给img自定义一个属性,比如“data-src”,将图片的真实地址保存到自定义属性中,当元素出现在浏览器的可视范围内时,将自定义的data-src属性值赋值给图片的src属性。

准备

data-*: 标签的自定义属性
offsetTop: 离其最近的定位元素的顶部的距离,如果没有则是相对于body顶部的距离
availHeight: window.screen.availHeight 浏览器的可用范围高度
scrollTop:document.body.scrollTop 浏览器因滚动而隐藏的高度,Chrome浏览器下是document.documentElement.scrollTop

实现步骤

1、给img标签添加自定义属性data-src,将图片的真实地址保存到data-src属性中,暂不设置src
2、页面加载完成后,判断img是否在用户可视范围内,如果是则将data-src的值赋给src
3、添加滚动事件监听,滚动时判断img是否出现在用户可视范围内,如果是则将data-src的值赋给src

实现代码


<html>
<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>图片的懒加载title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    #ul {
      width: 200px;
      outline: 1px dashed #f00;
      list-style: none;
    }
    #ul > li {
      width: 180px;
      height: 100px;
      margin-bottom: 50px;
      outline: 1px dashed #0f0;
    }
    .img {
      width: 100%;
      height: 100%;
    }
  style>
head>
<body>
  <div class="wrapper">
    <ul id="ul">
      <li><img class="img" data-src="https://img.alicdn.com/imgextra/i3/1886487777/O1CN0127JufVir7DmPYpu_!!1886487777-0-daren.jpg_360x360xzq90.jpg" >li>
      <li><img class="img" data-src="https://img.alicdn.com/imgextra/i2/2585780740/O1CN011HKxYBjGug0VPwX_!!2585780740-0-beehive-scenes.jpg_360x360xzq90.jpg" alt="" >li>
      <li><img class="img" data-src="https://img.alicdn.com/tfscom/i4/2310153969/TB1.C3aiH1YBuNjSszeXXablFXa_!!0-item_pic.jpg_360x360xzq90.jpg" alt="" >li>
      <li><img class="img" data-src="https://img.alicdn.com/imgextra/i1/3158956210/TB25uKZssyYBuNkSnfoXXcWgVXa_!!3158956210-0-beehive-scenes.jpg_360x360xzq90.jpg" alt="" >li>
      <li><img class="img" data-src="https://img.alicdn.com/tfscom/TB2CXy1XerAQeBjSZFrXXbSvFXa_!!0-dgshop.jpg_360x360xzq90.jpg" alt="" >li>
      <li><img class="img" data-src="https://img.alicdn.com/bao/uploaded/TB2EUU6w8mWBuNkSndVXXcsApXa_!!2306497993.jpg_360x360xzq90.jpg" alt="" >li>
      <li><img class="img" data-src="https://img.alicdn.com/bao/uploaded/TB2PfjytbSYBuNjSspiXXXNzpXa_!!395676295-0-beehive-scenes.jpg_360x360xzq90.jpg" alt="" >li>
      <li><img class="img" data-src="https://img.alicdn.com/bao/uploaded/TB2Mb.9X4PI8KJjSspoXXX6MFXa_!!2948425669-0-beehive-scenes.jpg_360x360xzq90.jpg" alt="" >li>      
      <li><img class="img" data-src="https://img.alicdn.com/bao/uploaded/TB2MGqTbLTJXuFjSspeXXapipXa_!!867439872.jpg_360x360xzq90.jpg" alt="" >li>
      <li><img class="img" data-src="https://aecpm.alicdn.com/simba/img/TB1j4LLKpXXXXcbaXXXSutbFXXX.jpg" alt="" >li>
      <li><img class="img" data-src="https://aecpm.alicdn.com/simba/img/TB13xKuLVXXXXcHapXXSutbFXXX.jpg" alt="" >li>
      <li><img class="img" data-src="https://aecpm.alicdn.com/simba/img/TB1X6uHLVXXXXcCXVXXSutbFXXX.jpg" alt="" >li>
      <li><img class="img" data-src="https://img.alicdn.com/imgextra/i2/57/O1CN01TfSEXR1CI93oiwRz7_!!57-0-lubanu.jpg_350x350q90.jpg" alt="" >li>
      <li><img class="img" data-src="https://img.alicdn.com/imgextra/i3/48/O1CN01zKg3pd1CE1UnQ2TD3_!!48-0-lubanu.jpg_350x350q90.jpg" alt="" >li>
    ul>
  div>
  <script>
    function lazyload() {
      let img = document.getElementsByClassName('img')
      let availHeight = window.screen.availHeight // 浏览器可用部分高度
      let scrollTop = document.body.scrollTop || document.documentElement.scrollTop // 滚动隐藏的高度
      for(let i = 0; i < img.length; i++) {
        if(img[i].offsetTop - scrollTop < availHeight) {  // 判断条件,元素是否出现在用户视野内
          let src = img[i].getAttribute('data-src') // 获取真实地址
          if(src) { // 如果获取到了 data-src 说明图片是第一次出现在视野内
            img[i].setAttribute('src', src) // 将真实地址赋给图片的src属性
            img[i].removeAttribute('data-src') // 移除data-src
          }
        }
      }
    }
    window.onload = lazyload // 页面加载执行 lazyload
    window.onscroll = lazyload // 监听滚动事件,滚动时执行lazyload
  script>
body>
html>

这样就实现了图片的懒加载。似乎没什么问题,但在看一下offsetTop:“离其最近的定位元素的顶部的距离,如果没有则是相对于body顶部的距离”。如果其祖先元素没有定位则没问题,但是如果图片的父元素position是relative或者是absolute,但是这个父元素并未出现在用户视野内,图片仍然可能已经加载了,这样并未达到懒加载的目的。

改进offsetTop

为了解决上面的问题,就要获得元素相对于body的“offsetTop”,我们可以写一个函数来获得这个距离。

function getOffsetByBody(el) {
	let offsetTop = 0
	while(el && el.tagName !== 'BODY') {
		offsetTop += el.offsetTop
		el = el.offsetParent
	}
	return offsetTop
}

这样我们就获得了当前元素相对于body顶部的偏移距离。经过改写后的JS部分如下:

function getOffsetByBody(el) {
	let offsetTop = 0
	while(el && el.tagName !== 'BODY') {
		offsetTop += el.offsetTop
		el = el.offsetParent
	}
	return offsetTop
}
function lazyload() {
      let img = document.getElementsByClassName('img')
      let availHeight = window.screen.availHeight // 浏览器可用部分高度
      let scrollTop = document.body.scrollTop || document.documentElement.scrollTop // 滚动隐藏的高度
      for(let i = 0; i < img.length; i++) {
      	 let offsetTop = getOffsetByBody(img[i])
        if(offsetTop - scrollTop < availHeight) {  // 判断条件,元素是否出现在用户视野内
          let src = img[i].getAttribute('data-src') // 获取真实地址
          if(src) { // 如果获取到了 data-src 说明图片是第一次出现在视野内
            img[i].setAttribute('src', src) // 将真实地址赋给图片的src属性
            img[i].removeAttribute('data-src') // 移除data-src
          }
        }
      }
    }
    window.onload = lazyload // 页面加载执行 lazyload
    window.onscroll = lazyload // 监听滚动事件,滚动时执行lazyload

github预览地址:https://zjinxing.github.io/PicLazyload/index.html

你可能感兴趣的:(javascript)