图片懒加载

352 阅读3分钟

在前端的性能优化里面常常提及图片加载优化,实现方案会有雪碧图、图片压缩以及懒加载。所谓图片懒加载,道理同组件懒加载类似,只有当页面需要使用到的时候再去请求图片。

如何实现图片懒加载?

1、使用vue-loayload插件

插件的使用遵循 下载->引入->安装->使用 四个步骤

下载:

npm i vue-lazyload -S

引入和安装:可以在main.js中全局引入,也可以单文件里面局部引入,其实配置项可以参考

import lazyload from 'vue-lazyload';
Vue.use(lazyload, {// 第二个参数表示配置项
  loading: require('@/assets/images/common/default.png'),
  error: require('@/assets/images/common/default.png'),
})

使用:

<img v-lazy="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/a4aa0cbfad7de34618c4bebdbdeee4e1.jpg?w=2452&h=920">

貌似在更改图片地址的时候会存在视图不更新的情况,此时可以通过给img元素增加key值解决,尴尬的是我没遇到过~~~

一不小心翻到大佬手写的v-lazyload指令github地址,效果与v-lazy类似,赶紧收藏起来膜拜下,下面自己手写的表示弱爆了呀。

2、手写

听说不喜欢自己造轮子的前端不是好前端,这话我听谁说的呀,捂脸。

实现方案:1、定义中间变量用于存储图片地址;

2、监听容器滚动事件,把图片地址赋给要展示的元素;

3、建议固定容器宽高,避免页面重排(回流),当服务器请求缓慢或请求失败时使用默认图片。

一言不合就喜欢上代码~~~非常不要脸的推荐胡邹邹的码云

<template>
  <section class="vh100 oa" @scroll="scroll" ref='sec'>
    <ul>
      <li v-for="(item, index) in imgList" :key="index">
        <img :src="item.imgSrc||defaultImg" @error="doError(item)">
      </li>
    </ul>
  </section>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator';
interface ImgItem {
  imgSrc: string;
  imgUrl: any;
}
@Component
export default class PicLazyLoad extends Vue {
  private defaultImg: any = require('../../assets/images/common/default.png');
  private imgList: ImgItem[] = [
    { imgSrc: '', imgUrl: 'https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/a4aa0cbfad7de34618c4bebdbdeee4e1.jpg?w=2452&h=920'},
    { imgSrc: '', imgUrl: 'https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/fc7c5cc595e12203796678eedd9c4250.jpg?thumb=1&w=1533&h=575&f=webp&q=90'},
    { imgSrc: '', imgUrl: 'https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/e45bcdea59448cd82360662a331409fc.jpg?thumb=1&w=1533&h=575&f=webp&q=90'},
    { imgSrc: '', imgUrl: 'https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/a38b1d56409913d5dc869023ade36d94.jpg?thumb=1&w=1533&h=575&f=webp&q=90'},
    { imgSrc: '', imgUrl: 'https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/6bd4174b8c5aad67a64864a5716ad152.jpg?thumb=1&w=1533&h=575&f=webp&q=90'},
  ];
  private imgH: number = 0; // 图片高度
  private clientH: number = document.documentElement.clientHeight; // 视口高度
  private curImg: number = 0; // 当前展示图片
  private created() {
    console.warn('图片懒加载,主要用于需要加载大量图片时,优先加载首屏图片,其他屏幕图片滚动加载');
    console.warn('优化图片加载失败时使用默认图片');
  }
  private mounted() {
    this.imgH = (document.querySelector('img') as any).getBoundingClientRect().height;
    this.curImg = Math.floor(this.clientH / this.imgH);
    this.imgList.forEach((item, index) => {
      if ( index <= this.curImg ) {
        item.imgSrc = item.imgUrl;
      }
    });
  }
  private scroll() {
    const scrollTop: number = (this.$refs.sec as any).scrollTop;
    const acc: number = Math.floor(scrollTop / this.imgH);
    setTimeout( () => this.imgList[this.curImg + acc].imgSrc = this.imgList[this.curImg + acc].imgUrl, 500);
  }
  private doError(item: ImgItem) {
    item.imgSrc = '';
  }
}
</script>

<style lang="scss" scoped>
img {
  width: 153*5px;
  height: 57*5px;
}
</style>

ts写的不溜,啥时候能来个人赏个赞指点一下^^,我太难了@_@