likes
comments
collection
share

✍优化系列之「图片懒加载」

作者站长头像
站长
· 阅读数 65

前言

在此之前我们先了解下js中几个和滚动相关的属性。

  1. offsetTop :当前元素到 offsetParent 的距离。
  2. offsetParent:距离当前元素最近的一个有定位的祖宗元素,如果没有默认是body。
  3. offsetWidth: width + 左右padding + 左右border
  4. offsetHeight: height + 上下padding + 上下border

✍优化系列之「图片懒加载」

  1. clientWidth: width + 左右padding
  2. clientHeight: height + 上下padding
  3. clientTop = boder.top(上边框的宽度)
  4. clientLeft = boder.left(左边框的宽度)

✍优化系列之「图片懒加载」

  1. scrollWidth:获取指定标签内容层的真实宽度(可视区域宽度+被隐藏区域宽度)
  2. scrollHeight:获取指定标签内容层的真实高度(可视区域高度+被隐藏区域高度)
  3. scrollTop: 内容层顶部到可视区域顶部的距离
  4. scrollLeft: 内容层左端 到 可视区域左端的距离

✍优化系列之「图片懒加载」

案例实现

原理

当有很多图片的时候,如果选择一次性渲染所有图片,非常的耗费性能,这个时候优先加载可视区域内的图片,其他图片当用户滑动到可视区域再进行加载的技术就是图片懒加载。

思路分析

实现图片懒加载的方式有很多种,这里介绍的是利用图片的offsetTop特性。上面介绍了offsetTop等于当前元素到offsetParent的距离,这里我们可以将需要展示图片的窗口设置定位,当图片的offsetTop < scrollTop + clientHeight 的时候代表当前的图片已经出现,那么此时就去加载当前图片。

✍优化系列之「图片懒加载」

在vue中实现

这里用循环的形式模拟后端图片资源
export default function getPngImg(num) {
  if (typeof num !== "number" || num < 1) return
  let imgs = []
  for (let i = 0; i < num; i++) {
    let src = `https://robohash.org/${i}.png`
    imgs.push(src)
  }
  return imgs
}
将真实的图片地址存储在data-src中
<template>
  <div class="box" ref="box">
    <ul v-for="item in imgSrcs" :key="item">
      <li>
        <img :data-src="item" alt="" ref="view" class="picture" />
      </li>
    </ul>
  </div>
</template>


<script>
import getPngImg from "../Imgs/production-img.js";
export default {
  setup() {
    return {
      imgSrcs: getPngImg(10),
    };
  },
 }
</script>

这里用 data-src 暂时设置为真实的图片,方便后面替换,可以将 src 设置为 loading 图片,我这里没有找到 loading 图片就没有设置。

将 data-src 地址替换 src 图片地址
  mounted() {
    this.lazyLoad();
    this.$refs.box.addEventListener("scroll", this.handleScroll, true);
  },

  methods: {
    handleScroll() {
      debounce(this.lazyLoad, 100);
    },
    lazyLoad() {
      const imgs = this.$refs.image;
      const scrollTop = this.$refs.box.scrollTop;
      const clientHeight = this.$refs.box.clientHeight;
      for (var i = 0; i < imgs.length; i++) {
        if (clientHeight + scrollTop > imgs[i].offsetTop) {
          imgs[i].src = imgs[i].getAttribute("data-src");
        }
      }
    },
  },

因为scroll事件触发的非常频繁,这里面使用了一个防抖函数,也可以使用节流函数,具体的防抖函数写法如下:

/**
 * 防抖函数
 *
 * @param fn - 目标函数
 * @param timer - 等待时间
 */

export default function debounce(fn, timer) {
  if (Object.prototype.toString.call(fn).slice(8, -1) !== "Function" || typeof timer !== "number") return
  clearTimeout(debounce.T)
  debounce.T = setTimeout(() => {
    fn()
  }, timer)
}

也可以使用 vue-lazyload 插件实现

  1. 安装插件
npm install vue-lazyload --save-dev
  1. 在main.js文件中引入并使用
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload)
  1. 修改图片显示方式为懒加载(将 :src="xxx" 属性直接改为v-lazy="xxx")
转载自:https://juejin.cn/post/7239296984984535101
评论
请登录