Vue.js的图片加载性能优化你可以试试

Jacquelyn38
• 阅读 2263

前言

图片加载优化对于一个网站性能好坏起着至关重要的作用。所以我们使用Vue来操作一波。

备注

以下的优化一、优化二栏目都是我自己封装在Vue的工具函数里,所以请认真看完,要不然直接复制的话,容易出错的。

资源

  • Vue.js

  • Element UI

优化一:图片加载动画

只有当图片加载完成后才可以显示图片,加载动画结束。我们使用Element UI中的loading组件来用作加载的动画。假设一个变量loading初始值为true,当图片加载完时为false

 // 图片加载  
    imgLoad:(src)=>{  
      let bgImg = new Image();  
      bgImg.src = src; // 获取背景图片的url  
      bgImg.onerror = () => {  
        console.log("img onerror");  
      };  
      bgImg.onload = () => {  
        // 等背景图片加载成功后 去除loading  
        console.log("加载完成");  
        return false  
      };  
    },

优化二:图片懒加载

当图片处于视口位置时,才会请求图片。这个优化不仅可以用在网站首页,还可以用在图片比较多的网页,节约性能。话不多说,我们来实现一波。

 // 获取图片距离   
    getRect(element) {  
      const rect = element.getBoundingClientRect();  
      const top = !document.documentElement.clientTop ? document.documentElement.clientTop : 0;  
      const left = !document.documentElement.clientLeft ? document.documentElement.clientLeft : 0;  
      return {  
          top: rect.top - top,  
          bottom: rect.bottom - top,  
          left: rect.left - left,  
          right: rect.right - left  
      }  
    },  
    // 封装图片懒加载  
    lazyload() {  
      let img = document.getElementsByTagName("img");  
      let len = img.length;  
      let n = 0; // 存储图片加载到的位置,避免每次都从第一张图片开始遍历  
      // 可见区域高度  
      const seeHeight = window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight;   
      for (let i = n; i < len; i++) {  
          // 如果图片距顶部距离小于可见区域高度与滚动条距离顶部高度之和时,才显示图片  
          let rectTop = this.getRect(img[i]).top;      // 这里的this.getRect()是用来获取图片位置的。  
          let rectBottom= this.getRect(img[i]).bottom;   
          if (rectTop > 0 && rectTop < seeHeight && rectBottom > 0 && rectBottom < seeHeight) { // 已经在视口  
              img[i].getAttribute("src") === ""?(img[i].setAttribute('class', 'opacity'),img[i].src = img[i].getAttribute("data-src")):n = i + 1;  
          } else if(rectTop < seeHeight && rectBottom >= seeHeight){ // 正在进入视口  
              img[i].getAttribute("src") === ""?(img[i].setAttribute('class', 'opacity'),img[i].src = img[i].getAttribute("data-src")):n = i + 1;  
          }  
      }  
    }

这里的设置类名opacity可以自己根据喜欢的动画设置。我这里写的是这样的,可以参考一下。

.opacity {  
  animation: 0.3s ani linear;  
}  
@keyframes ani {  
  0% {  
    opacity: 0;  
    transform: translateX(-200px);  
  }  
  100% {  
    opacity: 1;  
    transform: translateX(0px);  
  }  
}  

整合工具包

我们做Vue脚手架项目时,经常会用到很多重复的代码段或者方法函数,所以我们可以封装起来,想用的时候就用,也避免了代码冗余。

1、在src根目录下创建util文件夹,里面创建util.js;

2、在src根目录下的main.js中键入以下代码,引入util.js,并且全局注册;

import utils from './util/util'  

Vue.prototype.$utils=utils  

3、编辑util.js;

export default {  
    // 图片加载  
    imgLoad:(src)=>{  
      let bgImg = new Image();  
      bgImg.src = src; // 获取背景图片的url  
      bgImg.onerror = () => {  
        console.log("img onerror");  
      };  
      bgImg.onload = () => {  
        // 等背景图片加载成功后 去除loading  
        console.log("加载完成");  
        return false  
      };  
    },   
    // 获取元素距离   
    getRect(element) {  
      const rect = element.getBoundingClientRect();  
      const top = !document.documentElement.clientTop ? document.documentElement.clientTop : 0;  
      const left = !document.documentElement.clientLeft ? document.documentElement.clientLeft : 0;  
      return {  
          top: rect.top - top,  
          bottom: rect.bottom - top,  
          left: rect.left - left,  
          right: rect.right - left  
      }  
    },  
    // 封装图片懒加载  
    lazyload() {  
      let img = document.getElementsByTagName("img");  
      let len = img.length;  
      let n = 0; // 存储图片加载到的位置,避免每次都从第一张图片开始遍历  
      // 可见区域高度  
      const seeHeight = window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight;   
      for (let i = n; i < len; i++) {  
          // 如果图片距顶部距离小于可见区域高度与滚动条距离顶部高度之和时,才显示图片  
          let rectTop = this.getRect(img[i]).top;  
          let rectBottom= this.getRect(img[i]).bottom;  
          if (rectTop > 0 && rectTop < seeHeight && rectBottom > 0 && rectBottom < seeHeight) {  
              img[i].getAttribute("src") === ""?(img[i].setAttribute('class', 'opacity'),img[i].src = img[i].getAttribute("data-src")):n = i + 1;  
          } else if(rectTop < seeHeight && rectBottom >= seeHeight){  
              img[i].getAttribute("src") === ""?(img[i].setAttribute('class', 'opacity'),img[i].src = img[i].getAttribute("data-src")):n = i + 1;  
          }  
      }  
    }  
}  

实例

我们封装了工具函数,那么我们就使用它,这里使用this.$utils调用每个方法。

应用:图片加载动画

我们在一个页面这样使用了它,this.bannerSrc是图片地址,this.loading是加载动画的状态。

 mounted() {  
    if (!this.$utils.imgLoad(this.bannerSrc)) {  
      this.loading = false;  
    }  
  }

应用:图片懒加载

1、设置keep-alive的页面

methods: {  
    // 懒加载图片  
    scrollView() {  
      const fn = this.$utils.lazyload.bind(this.$utils);  
      window.addEventListener("scroll", fn);  
      // 离开组件  
      this.$once("hook:deactivated", function() {  
        window.removeEventListener("scroll", fn);  
      });  
    }  
  },  
  activated() {  
    this.scrollView();  
  },  
  mounted() {  
     this.$utils.lazyload(); // 初始化  
  }

2、未设置keep-alive的页面

 mounted() {  
    this.$utils.lazyload();  
    window.addEventListener("scroll", this.$utils.lazyload.bind(this.$utils));  
  },  
  beforeDestroy(){  
    window.removeEventListener("scroll", this.$utils.lazyload.bind(this.$utils));  
  }

IntersectionObserver

这是h5的api,IntersectionObserver。不过兼容性不好,大家可以试一下。

const io = new IntersectionObserver(dom);  
 let imgs = document.querySelectorAll('[data-src]');  
 function dom(entries){  
  entries.forEach((item) => {  
   if(item.isIntersecting){  
        console.log(1)  
    item.target.src = item.target.dataset.src   
    io.unobserve(item.target)   
   }  

  })  
 }   
 imgs.forEach((item)=>{  
  io.observe(item)  
 })  

结语

如果觉得有用,不妨关注一下哦~

作者:「Vam的金豆之路」

主要领域:「前端开发」

我的微信:「maomin9761」

微信公众号:「前端历劫之路」Vue.js的图片加载性能优化你可以试试

本文转转自微信公众号前端历劫之路原创https://mp.weixin.qq.com/s/y0fz8d-9P12cW3F8QQLzXA,如有侵权,请联系删除。

点赞
收藏
评论区
推荐文章
Dax Dax
2年前
前端性能优化
前端性能优化1、减少资源的请求次数和大小压缩合并js和css文件,减少http请求次数和请求资源的大小;在项目中使用webpackglup等打包编译工具2、尽量使用字体图标或者svg图标代替传统的png(jpg)图渲染更快,减少代码体积,且放大不会出现变形等3、使用图片懒加载目的是减少页面第一次加载的http请求次数,实现思路:
爱丽丝13 爱丽丝13
2年前
聊聊前端性能优化
为什么要做性能优化?性能优化有多重要?网站的性能对于用户的留存率、转化率有很大的影响,直白的说,提高网站的性能可以直接提高网站带来的收益。性能优化的分类前端的性能优化主要分为两类:1.加载时优化;2.运行时优化;例如压缩文件、使用CDN加载静态资源属于加载时优化;及时的解绑事件、减少DOM的操作属于运行时优化。吉
巴拉米 巴拉米
2年前
前端性能优化
为什么要做性能优化?性能优化有多重要?网站的性能对于用户的留存率、转化率有很大的影响,直白的说,提高网站的性能可以直接提高网站带来的收益。性能优化的分类前端的性能优化主要分为两类:1.加载时优化;2.运行时优化;例如压缩文件、使用CDN加载静态资源属于加载时优化;及时的解绑事件、减少DOM的操作属于运行时优化。吉
浩浩 浩浩
2年前
【Flutter实战】图片和Icon
3.5图片及ICON3.5.1图片Flutter中,我们可以通过Image组件来加载并显示图片,Image的数据源可以是asset、文件、内存以及网络。ImageProviderImageProvider是一个抽象类,主要定义了图片数据获取的接口load(),从不同的数据源获取图片需要实现不同的ImageProvi
Stella981 Stella981
2年前
Egret白鹭开发小游戏之自定义load加载界面
刚接触不久就遇到困难自定义loading。想和其他获取图片方式一样获取加载界面的图片,结果发现资源还没加载就需要图片,在网上百度了许多,都没有找到正确的方式,通过自己的摸索,终于,,,我成功了。。。下面介绍一下主要思想:首先,我们需要使用异步加载的方式,在加载界面之前加载loading界面需要的素材,然后再loadingUI中就可以大胆使
Wesley13 Wesley13
2年前
KO
KOKO是一个基于Webpack开发的快速开始Web开发的脚手架工具,具有以下特性:可以当做一个Webpack配置种子来使用,无需二次配置、开箱即用自动支持多页应用(可选)Vue单文件组件的开发方式资源分块加载,内联和异步加载方式管理,低成本实现首屏优化支
Wesley13 Wesley13
2年前
6 招教你提高网站速度
!图片1(https://image.evget.com//Content/files/2017/7/28/5174b527782a4fcca1e997eba85dfe89636368468467682067.gif)①图片优化统计数据显示,用户倾向于放弃一个在3秒内未加载完成的网页。由于加载图片占据了网页上可下载的大部分字节空间,所以
Stella981 Stella981
2年前
Fastdfs安装_nginx进行图片动态压缩
说明1.因为上传的图片较大,部分页面直接引用图片地址,则造成页面加载缓慢问题。2.考虑到服务器空间问题,我们没有进行上传缩略图。仅仅是上传了原图3.为了优化页面加载图片的时间问题,所以对图片进行动态缩放。PS:如果访问量较高,建议进行存储缩略图图片缩放采用nginx的http\_image\_filter\_module
京东云开发者 京东云开发者
6个月前
深入理解 Flutter 图片加载原理 | 京东云技术团队
Flutter官方为我们提供了Image控件可实现图片的加载及显示,Image控件本身是一个StatefulWidget,那么在图片显示过程中是如何加载及显示出来的呢?本篇文章将逐步分析Flutter中图片加载原理,理解了Flutter图片源码的加载原理后对我们有什么帮助?
京东云开发者 京东云开发者
6个月前
React请求机制优化思路 | 京东云技术团队
说起数据加载的机制,有一个绕不开的话题就是前端性能,很多电商门户的首页其实都会做一些垂直的定制优化,比如让请求在页面最早加载,或者在前一个页面就进行预加载等等。