背景
渲染图片资源时,资源过多过大,空白期会过长;如果希望马上呈现,而不是慢慢加载,就要用到图片预加载
原理,是利用浏览器缓存机制:访问同一张地址的图片,只请求图片一次。将这个请求的时机提前,把资源提前加载好(如果是首页,也可先放置加载gif,加载资源后切换src), 提前加载的实现,可new Image()去模拟,加载后将image置为null。
代码实现
utiljs
/**
* promise
* 基本的图片预加载
*/
/**
* promise
* @param {*} url
* @returns
* 基本的图片预加载
*/
const imgPreloader = url => {
return new Promise((resolve, reject) => {
//新建image对象去加载url
let temp = new Image();
temp.src = url
temp.onload = () => {
//加载完成 执行resolve
window.console.log('onload')
resolve('true');
};
temp.onerror = () => {
window.console.log('onerror')
reject('false');
};
//清除image对象
temp=null
});
}
/**
* promise.all并行响应
* @param imgs 图片路径数组
* @returns {Promise<unknown[]>}
*/
const allImgPreloader = imgs => {
let promiseArr = new Array()
imgs.forEach(url => {
//所有加载promise
promiseArr.push(imgPreloader(url))
})
//执行结果
return Promise.all(promiseArr)
}
export default allImgPreloader
index.vue
<template>
<div class="homeView">
<img v-for="(item, index) in imgs" :src="item" alt="" :key="index"> </div>
</template>
<script>
//引入子组件
import allImgPreloader from './preloadUtil.js'
export default {
name: "HomeView",
//注册子组件
components: {
},
data() {
return {
imgs: [ //require相对路径
require('../../imgs/pic1.png'),
require('../../imgs/pic2.png'),
require('../../imgs/pic3.png'),
require('../../imgs/pic4.png'),
require('../../imgs/pic5.png'),
require('../../imgs/pic6.png'),
]
}
},
created() {
this.begin()
},
methods: {
/**
* 异步function 处理onload
*/
preImg() {
//调用
return allImgPreloader(this.imgs)
},
async begin() {
//预加载时展示加载loading
const toast = this.$toast.loading({
duration: 0, // 持续展示 toast
forbidClick: true,
message: '预加载中...'
});
let resultList = await this.preImg()
window.console.log('list', resultList)
//promise执行完毕 做后面的逻辑 比如清除loading
toast.clear()
}
}
}
</script>
<style scoped>
.homeView {
width: 80%;
height: auto;
margin: auto;
}
img {
width: 100px;
height: 100px;
}
</style>
总结
封装时,new Image加载图片资源,加载后对象置空;封装为promise,多个则放入Promise.all;使用时结合async await,在预加载开始和结束时,做loading的渲染和清除等操作。