Vue回炉重造之图片加载性能优化

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

前言


图片加载优化对于一个网站性能好坏起着至关重要的作用。所以我们使用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));
  }



相关文章
|
5天前
|
JavaScript
vue消息订阅与发布
vue消息订阅与发布
|
2天前
|
JavaScript
理解 Vue 的 setup 应用程序钩子
【10月更文挑战第3天】`setup` 函数是 Vue 3 中的新组件选项,在组件创建前调用,作为初始化逻辑的入口。它接收 `props` 和 `context` 两个参数,内部定义的变量和函数需通过 `return` 暴露给模板。`props` 包含父组件传入的属性,`context` 包含组件上下文信息。`setup` 可替代 `beforeCreate` 和 `created` 钩子,并提供类似 `data`、`computed` 和 `methods` 的功能,支持逻辑复用和 TypeScript 类型定义。
20 11
|
4天前
|
JavaScript
vue尚品汇商城项目-day07【vue插件-50.(了解)表单校验插件】
vue尚品汇商城项目-day07【vue插件-50.(了解)表单校验插件】
14 4
|
4天前
|
JavaScript
vue尚品汇商城项目-day07【51.路由懒加载】
vue尚品汇商城项目-day07【51.路由懒加载】
15 4
|
6天前
|
JavaScript 前端开发
Vue学习笔记8:解决Vue学习笔记7中用v-for指令渲染列表遇到两个问题
Vue学习笔记8:解决Vue学习笔记7中用v-for指令渲染列表遇到两个问题
|
4天前
|
JavaScript
vue尚品汇商城项目-day07【vue插件-54.(了解)生成二维码插件】
vue尚品汇商城项目-day07【vue插件-54.(了解)生成二维码插件】
14 2
|
6天前
|
JavaScript 前端开发 API
Vue学习笔记7:使用v-for指令渲染列表
Vue学习笔记7:使用v-for指令渲染列表
|
7天前
|
JavaScript
vue组件中的插槽
本文介绍了Vue中组件的插槽使用,包括单个插槽和多个具名插槽的定义及在父组件中的使用方法,展示了如何通过插槽将父组件的内容插入到子组件的指定位置。
|
6天前
|
JavaScript 前端开发 IDE
Vue学习笔记5:用Vue的事件监听 实现数据更新的实时视图显示
Vue学习笔记5:用Vue的事件监听 实现数据更新的实时视图显示
|
6天前
|
JavaScript 前端开发 API
Vue学习笔记4:用reactive() 实现数据更新的实时视图显示
Vue学习笔记4:用reactive() 实现数据更新的实时视图显示
下一篇
无影云桌面