图片懒加载

235 阅读1分钟

1.图片懒加载有两种方式

默认图片可视区由父元素的高度决定

1.1 第一种使用offsetTop

步骤一: 获取图片元素列表

//父元素
let box = document.querySelector(".box");
//元素列表
let elements = document.querySelectorAll("img");

步骤二:遍历元素列表

elements.forEach((item, index) => {
    
})

步骤三:判断图片是否在可视区

//得到每个元素相对于父元素可视区top距离
let positionY = item.offsetTop - '第一个img相对有offsetParent属性的父元素的距离';
//这里注意:如果box父元素有设置paddingtop,这里减去的就是box父元素相对含有offsetParent属性的父元素的距离

// img元素相对含offsetParent属性的父元素的距离-滚动条滚动的距离<可视区的高度 就说明图片已经进入可视区
if (positionY-box.scrollTop < box.clientHeight) {
  let url = arr[index].imgUrl;
  arr[index].imgUrl=""
  arr[index].real_url = url
}

注意:offsetTop不是相对父元素的距离,而是相对含offsetParent属性的上层元素的距离,而 含有 定位属性(position)的元素或者 本身就是 table,td,th,body 的元素,就具备 offsetParent的属性,如果没有就是相对于body。

图示:当我去掉box的父元素的position定位之后首元素的offsetTop从60变为688,也就是变成相对于body的距离了。

1371666196396_.pic_thumb.jpg

图示:图片高度为100px,间距为10px

1351666195398_.pic.jpg

示例代码:

<template>
  <div class="box">
    <div
      class="box-item"
      v-for="(item, index) in datalist"
      :key="index"
    >
      <img :src="item.real_url" lazyload="true" :data-original="item.imgUrl" />
    </div>
  </div>
</template>

<script>
import { onMounted,onBeforeMount, ref } from "vue";
export default {
  setup() {
    const datalist = ref([
      {
        imgUrl: require("@/assets/bookface/cloud.png"),
        real_url: "",
      },
      {
        imgUrl: require("@/assets/bookface/河.jpg"),
        real_url: "",
      },
      {
        imgUrl: require("@/assets/bookface/snow.jpg"),
        real_url: "",
      },
      {
        imgUrl: require("@/assets/bookface/smoke.jpg"),
        real_url: "",
      },
      {
        imgUrl: require("@/assets/bookface/chonga.jpg"),
        real_url: "",
      },
      {
        imgUrl: require("@/assets/bookface/addoil.jpg"),
        real_url: "",
      },
      {
        imgUrl: require("@/assets/bookface/cloud.png"),
        real_url: "",
      },
      {
        imgUrl: require("@/assets/bookface/河.jpg"),
        real_url: "",
      },
      {
        imgUrl: require("@/assets/bookface/black.jpeg"),
        real_url: "",
      },
      {
        imgUrl: require("@/assets/bookface/moon.jpeg"),
        real_url: "",
      },
    ]);

    onBeforeMount(()=>{
      document.addEventListener("scroll",LazyLoad,true)
    })
    
    onMounted(() => {
      LazyLoad();
    });
    
    const LazyLoad = () => {
      const arr = datalist.value;
      let box = document.querySelector(".box");
      let elements = document.querySelectorAll("img");

      elements.forEach((item, index) => {
        let positionY = item.offsetTop - '第一个img相对有offsetParent属性的父元素的距离';
   
        if(!arr[index].imgUrl){
          return
        }
        
        if (positionY-box.scrollTop < box.clientHeight) {
          let url = arr[index].imgUrl;
          arr[index].imgUrl=""
          arr[index].real_url = url
        }
      });
    };
    return {
      datalist,
      LazyLoad,
    };
  },

};
</script>

<style lang="less" scoped>
.box {
  width:280px;
  height: 400px;
  overflow: hidden;
  overflow-y: scroll;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  &-item {
    box-sizing: border-box;
    width: 120px;
    height: 100px;
    background: cornflowerblue;
    margin-right: 10px;
    margin-bottom: 10px;
    img {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
  }
  .box-item:nth-of-type(even) {
    margin-right: 0;
  }
  .border {
    border: 2px solid salmon;
  }
}
</style>

1.2 第二种使用getBoundingClientRect

先了解一个api,getBoundingClientRect()可以获取元素的大小及位置,返回的是一个DOMRect的对象,包含元素的宽高,以及相对屏幕视口的位置。当图片滚动,图片位置发生变化,会触发getBoundingClientRect()返回每个元素相对视口的位置,所以我们可以根据 当元素相对视口的top值<=可视区的时候,就说明图片已经进入可视区(默认图片可视区为整个视口高度,如果不是的话需要减去可视区相对视口的top值)。

WechatIMG142.jpeg

核心代码:

const LazyLoad = () => {
      let box = document.querySelector(".box"); //父元素
      let elements = document.querySelectorAll("img"); //图片子元素集合

      elements.forEach((item, index) => {
        let positionY = item.getBoundingClientRect().top - '可视区相对屏幕视口的高度';
        
        if(!arr[index].imgUrl){
          return
        }
        if (positionY<=box.clientHeight) {
         //把图片地址赋给真实地址
        }
      });
    };