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

Jacquelyn38 等级 1089 1 1
标签:

前言

图片加载优化对于一个网站性能好坏起着至关重要的作用。所以我们使用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,如有侵权,请联系删除。

收藏
评论区

相关推荐

尤雨溪:TypeScript不会取代JavaScript
近日,Evrone 与 Vue.js 的作者尤雨溪进行了一次访谈,了解他对于无后端与全栈方法、以及 Vue.js 适用场景的看法,还有他本人如何在工作与生活之间取得平衡。 记者: 嗨 Evan,很荣幸你能接受我们的访谈。那就先从一个简单的问题开始:您的全职工作岗位是由 Patreon 资助的,大多数人恐怕都没有这样的机会。您能聊聊怎样在工作与生活之间找到
Angular和Vue.js 深度对比
Vue.js 是开源的 JavaScript 框架,能够帮助开发者构建出美观的 Web 界面。当和其它网络工具配合使用时,Vue.js 的优秀功能会得到大大加强。如今,已有许多开发人员开始使用 Vue.js 来取代 Angular 和 React.j
Vue.js——60分钟快速入门
是当下很火的一个JavaScript MVVM库,它是以数据驱动和组件化的思想构建的。相比于Angular.js,Vue.js提供了更加简洁、更易于理解的API,使得我们能够快速地上手并使用Vue.js。
浅谈Vue.js
作为一名Vue.js的忠实用户,我想有必要写点文章来歌颂这一门美好的语言了,我给它的总体评价是“简单却不失优雅,小巧而不乏大匠”,下面将围绕这句话给大家介绍Vue.js,希望能够激发你对Vue.js的兴趣。 注:本文介绍的是Vue1.×,目前Vue已经升级至2.×,功能和语法上有一定升级和修改,想了解2.×的请移步:Vue.js简介
Vue.js的图片加载性能优化你可以试试
前言图片加载优化对于一个网站性能好坏起着至关重要的作用。所以我们使用Vue来操作一波。备注以下的优化一、优化二栏目都是我自己封装在Vue的工具函数里,所以请认真看完,要不然直接复制的话,容易出错的。资源 Vue.js Element UI 优化一:图片加载动画只有当图片加载完成后才可以显示图片,加载动画结束。我们使用Element UI
15 个有趣的 JS 和 CSS 库
前端开发者们,一起来看看有木有你需要的前端库。 1.DisplayJS ----------- ![](https://oscimg.oschina.net/oscnet/a6f076a2-3828-479a-be8b-c09e572a4e9e.jpg) DisplayJS 是一个帮助你渲染 DOM 的简易框架。使用它,你可以更容易地将 J
02、Vue.js
1、插值 ====     在Vue.js指令学习之前,先简单学习一下Vue插值     语法:_**{{ }}**_,将vue 实例中的数据 写入到页面对应的位置。下面代码中hello、msg、num等均是在vue的data中定义的变量。 1.1 文本插值 -------- <div>{{hello}}<div> 1.2 HTML 标签插
1元速抢,黄轶老师的《Vue.js 3.0 源码解析》课程
你好,我是黄轶(ustbhuangyi), **现任 Zoom 前端架构师,曾先后于百度、滴滴从事前端研发工作。**平时喜欢钻研新技术、新框架,关注前端自动化、工程化、前端架构。 在 2019 年的 10 月 5 日, Vue.js的作者:尤雨溪在微博宣布 Vue 3.0 的源码开放了。 ![](https://oscimg.oschina.ne
10+个很酷的VueJS组件,模板和实验示例
众所周知,**Vue.js** 组件是Vue创建自定义元素的重要功能之一,同时,模板可帮助你避免从头开始创建网页设计。总之,这些工具对于希望其开发过程更快,更高效的任何Web开发人员都是必不可少的。 此外,在过去的几年中,Vue.js 变得非常流行,许多企业将其添加到他们的技术栈中。该框架的优点是它具有内置的数据绑定和MVC模型(模型、视图、控制器),
13个技巧让你的 vue.js 代码更优雅
前言🍊 ------- 作为深度代码洁癖,我们都希望能写出简单高效的代码,让我们的代码看起来更加优雅,让我们抛弃繁杂的代码,一起开启简单的旅程~~ ### $on(‘hook:’) 可以帮助你简化代码 mounted () {  window.addEventListener('resize', this.resizeHandler);
2016我的心路历程:从 Vue 到 Webpack 到 iView
> 2016年工作中做过最自豪的两件事情: * 把 Vue.js 和 Webpack 技术栈引进公司并逐步成为前端规范; * 开源 [iView](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fiview%2Fiview) 项目。 初识 Vue ===
2016我的心路历程:从 Vue 到 Webpack 到 iView
> 2016年工作中做过最自豪的两件事情: * 把 Vue.js 和 Webpack 技术栈引进公司并逐步成为前端规范; * 开源 [iView](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fiview%2Fiview) 项目。 初识 Vue ===
SpringBoot+Activiti+bpmn.js+Vue.js+Elementui
![](https://img2018.cnblogs.com/common/1431659/201912/1431659-20191220171610349-35038414.png) 一:activiti流程设计器的选择(通过学习activiti工作流过程中,发现一款好的流程设计器将会更好的方便的设计好流程(主要介绍BPMN.JS)) ========
Vue 全家桶
vue全家桶。 使用过vue的程序员一般这样评价它,“vue.js兼具angular.js和react.js的优点”。Vue.js 是一个JavaScript MVVM(Model-View-ViewModel)库,用于渐近式构建用户界面。它以数据驱动和组件化思想构建,采用自底向上增量开发的设计思想。相比Angular.js,Vue.js API更加简洁;
Vue 全家桶、原理及优化简议
不少互联网公司都在使用vue技术栈,或称为vue全家桶。 使用过vue的程序员一般这样评价它,“vue.js兼具angular.js和react.js的优点”。Vue.js 是一个JavaScript MVVM(Model-View-ViewModel)库,用于渐近式构建用户界面。它以数据驱动和组件化思想构建,采用自底向上增量开发的设计