图片懒加载的几种思路

图片的加载是由src引起的,给src赋值,浏览器请求图片资源。
使用HTML5的data-xxx属性存储图片路径,需要时赋值给src。

思路一:

图片加载条件:
imgs.offsetTop(元素到顶部距离) < window.innerHeight(浏览器可视区高度) 
+ document.body.scrollTop(滚动距离)

思路二:

检测图片进入浏览器可视区的时候加载图片

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .viewport {
      width: 300px;
      height: 200px;
      border: 1px solid blue;
      overflow: auto;
    }


    .box1 {
      height: 600px;
      width: 100%;
    }


    .observed {
      width: 100px;
      height: 100px;
      border: 1px solid green;
    }

    .imgs {
      width: 100px;
      height: 100px;
    }
  </style>
</head>

<body>
  <div class="viewport" id="viewport">
    <div class="box1">
      <img src="./place.jpg" data-src="http://p8.qhimg.com/bdr/__85/t01e5f605262fb61fb4.jpg" alt="图片" class="imgs" />
      <img src="./place.jpg" data-src="http://p8.qhimg.com/bdr/__85/t01e5f605262fb61fb4.jpg" alt="图片" class="imgs" />
      <img src="./place.jpg" data-src="http://p8.qhimg.com/bdr/__85/t01e5f605262fb61fb4.jpg" alt="图片" class="imgs" />
      <img src="./place.jpg" data-src="http://p8.qhimg.com/bdr/__85/t01e5f605262fb61fb4.jpg" alt="图片" class="imgs" />
      <img src="./place.jpg" data-src="http://p8.qhimg.com/bdr/__85/t01e5f605262fb61fb4.jpg" alt="图片" class="imgs" />
      <img src="./place.jpg" data-src="http://p8.qhimg.com/bdr/__85/t01e5f605262fb61fb4.jpg" alt="图片" class="imgs" />
      <img src="./place.jpg" data-src="http://p8.qhimg.com/bdr/__85/t01e5f605262fb61fb4.jpg" alt="图片" class="imgs" />
      <img src="./place.jpg" data-src="http://p8.qhimg.com/bdr/__85/t01e5f605262fb61fb4.jpg" alt="图片" class="imgs" />
      <img src="./place.jpg" data-src="http://p8.qhimg.com/bdr/__85/t01e5f605262fb61fb4.jpg" alt="图片" class="imgs" />
      <img src="./place.jpg" data-src="http://p8.qhimg.com/bdr/__85/t01e5f605262fb61fb4.jpg" alt="图片" class="imgs" />
      <img src="./place.jpg" data-src="http://p8.qhimg.com/bdr/__85/t01e5f605262fb61fb4.jpg" alt="图片" class="imgs" />
      <img src="./place.jpg" data-src="http://p8.qhimg.com/bdr/__85/t01e5f605262fb61fb4.jpg" alt="图片" class="imgs" />
      <img src="./place.jpg" data-src="http://p8.qhimg.com/bdr/__85/t01e5f605262fb61fb4.jpg" alt="图片" class="imgs" />
      <img src="./place.jpg" data-src="http://p8.qhimg.com/bdr/__85/t01e5f605262fb61fb4.jpg" alt="图片" class="imgs" />
      <img src="./place.jpg" data-src="http://p8.qhimg.com/bdr/__85/t01e5f605262fb61fb4.jpg" alt="图片" class="imgs" />
      <img src="./place.jpg" data-src="http://p8.qhimg.com/bdr/__85/t01e5f605262fb61fb4.jpg" alt="图片" class="imgs" />
    </div>
  </div>

  <script>
    let viewport = document.getElementById("viewport"); // 可视区域
    let imgList = document.querySelectorAll(".imgs"); // 被观察元素
    /* 开启观察者 */
    // var IO = new IntersectionObserver(回调,配置项)
    var IO = new IntersectionObserver(fn, {})
    function fn (entry) {
      console.log(entry, 'fn');
      entry.forEach(item => {
        if (item.isIntersecting) {
          /* 表示进入可是区域 */
          console.log(item.target.getAttribute('data-src'));
          // item.target.src = item.target.getAttribute('data-src')
          item.target.src = item.target.dataset.src
          IO.unobserve(item.target)
        } else {
          /* 离开 */
        }
      })
    }
    // console.dir(IO.observe());
    /* 观察img */
    imgList.forEach(item => {
      // console.log(item);
      IO.observe(item)
    })
  </script>
</body>

</html>

思路三:

@vueuse/core 中的useIntersectionObserver方法
<script setup>
import {onMounted} from "vue";
import { useIntersectionObserver } from '@vueuse/core'

    let itemRefs = []
    const setItemRef = el => {
      if (el) {
        itemRefs.push(el)
      }
    }

    //挂载后
    onMounted(()=>{
      //为各个div添加监控事件
      console.log("onMounted div的数量:"+itemRefs.length);
      for (let i=0;i<itemRefs.length;i++) {
        console.log(itemRefs[i]);
        useIntersectionObserver(itemRefs[i], ([{ isIntersecting }]) => {
          // 如果target对应的DOM进入可视区,那么该回调函数就触发
          console.log(isIntersecting);
          if (isIntersecting) {
            // 被监听的DOM进入了可视区:此时调用接口获取数据;停止继续监听
            stop()
            if (itemRefs[i].dataset.bg === '0') {
              console.log(`第"+${i+1}+"个div已显示`);
              //修改背景色
              itemRefs[i].dataset.bg = 1;
              itemRefs[i].style.background=getColor(i);
            }

          }
        })
      }
    })

    //返回颜色,使各个div区分开
    const getColor = (idx) => {
        if (idx == 0){
          return "#ffff00";
        } else if (idx == 1) {
          return "#ff00ff";
        } else if (idx == 2) {
          return "#00ffff";
        } else if (idx == 3) {
          return "#0000ff";
        } else if (idx == 4) {
          return "#00ff00";
        } else {
          return "#ff0000";
        }
    }
</script>

<template>
  <div>
    <div>
      <div data-bg="0" v-for="item in 5" :key="item" :ref="setItemRef" style="height: 500px;">
        第{{item}}个盒子
      </div>
    </div>
  </div>
</template>

思路四(小程序):

借用微信的内置 API 调用 IntersectionObserver 对象实例判断相交区域进行渲染

// pages/text/text.js
Page({
  data: {
      lazyList: [{
              imgUrl: "https://img0.baidu.com/it/u=2566646385,2213824192&fm=253&fmt=auto&app=138&f=JPEG?w=893&h=500"
          },
          {
              imgUrl: "https://img2.baidu.com/it/u=791640261,44080610&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800"
          },
          {
              imgUrl: "https://img0.baidu.com/it/u=1732772480,1050889914&fm=253&fmt=auto&app=138&f=JPEG?w=778&h=500"
          },
          {
              imgUrl: "https://img1.baidu.com/it/u=4001530358,139416054&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500"
          },
          {
              imgUrl: "https://img1.baidu.com/it/u=3006525416,739516061&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800"
          },
          {
              imgUrl: "https://img1.baidu.com/it/u=961451472,675417960&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500"
          },
          {
              imgUrl: "https://img0.baidu.com/it/u=4085930884,4214873769&fm=253&fmt=auto&app=120&f=JPEG?w=667&h=500"
          },
      ], //模拟数据
  },
  onLoad: function () {
      // 传入参数
      lazyImg(this, this.data.lazyList, 'lazyList', '../../assets/loading.gif')
  }
})

const lazyImg = (that, data, name, loadingImage) => {
  for (let i = 0, len = data.length; i < len; i++) {
      wx.createIntersectionObserver().relativeToViewport({
          bottom: 20
      }).observe('.item-' + i, (ret) => {
        console.log( (ret));
          ret.intersectionRatio > 0 ? data[i].show = true : '';
          that.setData({
              [name]: data,
              loading: loadingImage
          })
      })
  }
}



<!--pages/text/text.wxml-->
<view class='item-{{index}}' wx:for="{{lazyList}}" wx:key="*this.imgUrl">
  <!-- imgBox:图片类名 loadingImgBox:懒加载图片类名 -->
  <image src='{{item.show? item.imgUrl : loading}}' class='{{item.show? "imgBox" : "loadingImgBox"}}'></image>
</view>



/* pages/text/text.wxss */
image {
  width: 100%;
}
/* 懒加载图片样式 */
.loadingImgBox {
  transition: opacity 0.4s linear 0.4s;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值