Vue回爐重造之圖片加載性能優(yōu)化
前言
圖片加載優(yōu)化對(duì)于一個(gè)網(wǎng)站性能好壞起著至關(guān)重要的作用。所以我們使用Vue來操作一波。
備注
以下的優(yōu)化一、優(yōu)化二欄目都是我自己封裝在Vue的工具函數(shù)里,所以請(qǐng)認(rèn)真看完,要不然直接復(fù)制的話,容易出錯(cuò)的。
資源
Vue.js
Element UI
優(yōu)化一:圖片加載動(dòng)畫
只有當(dāng)圖片加載完成后才可以顯示圖片,加載動(dòng)畫結(jié)束。我們使用Element UI中的loading組件來用作加載的動(dòng)畫。假設(shè)一個(gè)變量loading初始值為true,當(dāng)圖片加載完時(shí)為false。
// 圖片加載
imgLoad:(src)=>{
let bgImg = new Image();
bgImg.src = src; // 獲取背景圖片的url
bgImg.onerror = () => {
console.log("img onerror");
};
bgImg.onload = () => {
// 等背景圖片加載成功后 去除loading
console.log("加載完成");
return false
};
},
優(yōu)化二:圖片懶加載
當(dāng)圖片處于視口位置時(shí),才會(huì)請(qǐng)求圖片。這個(gè)優(yōu)化不僅可以用在網(wǎng)站首頁,還可以用在圖片比較多的網(wǎng)頁,節(jié)約性能。話不多說,我們來實(shí)現(xiàn)一波。
// 獲取圖片距離
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; // 存儲(chǔ)圖片加載到的位置,避免每次都從第一張圖片開始遍歷
// 可見區(qū)域高度
const seeHeight = window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight;
for (let i = n; i < len; i++) {
// 如果圖片距頂部距離小于可見區(qū)域高度與滾動(dòng)條距離頂部高度之和時(shí),才顯示圖片
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) { // 已經(jīng)在視口
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){ // 正在進(jìn)入視口
img[i].getAttribute("src") === ""?(img[i].setAttribute('class', 'opacity'),img[i].src = img[i].getAttribute("data-src")):n = i + 1;
}
}
}
這里的設(shè)置類名opacity可以自己根據(jù)喜歡的動(dòng)畫設(shè)置。我這里寫的是這樣的,可以參考一下。
.opacity {
animation: 0.3s ani linear;
}
@keyframes ani {
0% {
opacity: 0;
transform: translateX(-200px);
}
100% {
opacity: 1;
transform: translateX(0px);
}
}
整合工具包
我們做Vue腳手架項(xiàng)目時(shí),經(jīng)常會(huì)用到很多重復(fù)的代碼段或者方法函數(shù),所以我們可以封裝起來,想用的時(shí)候就用,也避免了代碼冗余。
1、在src根目錄下創(chuàng)建util文件夾,里面創(chuàng)建util.js;
2、在src根目錄下的main.js中鍵入以下代碼,引入util.js,并且全局注冊(cè);
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; // 存儲(chǔ)圖片加載到的位置,避免每次都從第一張圖片開始遍歷
// 可見區(qū)域高度
const seeHeight = window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight;
for (let i = n; i < len; i++) {
// 如果圖片距頂部距離小于可見區(qū)域高度與滾動(dòng)條距離頂部高度之和時(shí),才顯示圖片
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;
}
}
}
}
實(shí)例
我們封裝了工具函數(shù),那么我們就使用它,這里使用this.$utils調(diào)用每個(gè)方法。
應(yīng)用:圖片加載動(dòng)畫
我們?cè)谝粋€(gè)頁面這樣使用了它,this.bannerSrc是圖片地址,this.loading是加載動(dòng)畫的狀態(tài)。
mounted() {
if (!this.$utils.imgLoad(this.bannerSrc)) {
this.loading = false;
}
}
應(yīng)用:圖片懶加載
1、設(shè)置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、未設(shè)置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));
}
作者:Vam的金豆之路
主要領(lǐng)域:前端開發(fā)
我的微信:maomin9761
微信公眾號(hào):前端歷劫之路