1.前言
最近自己在做一个博客类型的练习项目,因为网站没有备案无法使用cdn加速图片,所以每次进入网站时图片都加载的巨慢。因此,我想到了将图片的base64格式的数据存到本地(即浏览器)。刚开始我是用的localStorage存储数据,但是localStorage最多只能存储5M,后来我了解到还有没有存储限制的indexedDB来存储,我采用的是localforage对其进行简单的增删改查数据。
2.实现
2.1封装image组件
props: {
//图片的线上地址 https://...
src: {
default: null
},
//缓存到本地的Key值(键值)
cacheSrc: {
default: null
},
},
//通过Key值获取图片的base64数据
getSrc() {
if (this.cacheSrc == null)
return this.imageSrc = this.src
let newSrc = this.src || null
this.imageSrc = newSrc
try {
//异步
localforage.getItem(this.cacheSrc).then((res) => {
if (res == null)
this.downloadImage(this.src, this.cacheSrc)
else {
//判断一下图片是否更新,比如用户更换头像
if(this.src !== res?.oldSrc)
//下载图片
this.downloadImage(this.src, this.cacheSrc)
else this.imageSrc = res?.data
}
}).catch((err) => {
// 当出错时,此处代码运行
this.downloadImage(this.src, this.cacheSrc)
this.imageSrc = newSrc
console.log(err);
})
} catch (e) {
//TODO handle the exception
console.log(e)
this.imageSrc = newSrc
}
},
2.2下载图片并将图片转化为base64存储到本地
2.2.1下载图片
async function saveFileByH5(path, cacheData) {
const reader = new FileReader();
let imageBase64 = await urlToBase64(path)
// let imageBlob = base64ToBlob(imageBase64)
let image = {
...mode.getCacheMode(),
...cacheData
}
image.data = imageBase64
image.size = getBase64ImageSize(imageBase64)
setCache(image, "文件太大无法缓存")
return image
}
2.2.2转化为base64格式
function urlToBase64(url) {
return new Promise((resolve) => {
fetch(url).then(data => {
const blob = data.blob()
return blob;
}).then(blob => {
let reader = new FileReader()
reader.onloadend = function() {
const dataURL = reader.result
resolve(dataURL)
}
reader.readAsDataURL(blob)
})
})
}
2.2.3缓存到本地
async function setCache(file, message) {
try {
let name = file?.name || "未定义"
//列表
if(file?.list == true){
let listName = file?.listName || "未定义"
let oldData = await localforage.getItem(listName) || {}
oldData[name] = true
// uni.setStorageSync(name, file)
// uni.setStorageSync(listName, oldData)
localforage.setItem(name,file)
localforage.setItem(listName,oldData)
return
}
// uni.setStorageSync(name, file)
localforage.setItem(name,file)
} catch (error) {
console.log(error)
new Tip().error(error)
}
}