uni-app分享基于plus.downloader的图片懒加载功能,支持本地缓存v1.1.0
uni-app分享基于plus.downloader的图片懒加载功能,支持本地缓存v1.1.0
今天试用了下hello mui上的图片懒加载功能,发现有些地方还无法满足我的需求,ajax动态加载的时候无法实现懒加载。
然后又看了下36kr的示例,因为代码关系实在太多了,耦合度比较高,遂自己动手写了一个轻量级的懒加载功能模块,而且支持图片缓存到本地哦~~~
欢迎各位拍砖,交流碰撞思想!
升级日志
v1.1.0 build 20160107
- 已增加 @LFZ 的代码,不用重复下载两次服务器端的图片
- 新增图片加载淡入特效
- 新增图片加载完成后回调
- 修改data-src为data-lazyload
功能特性
- 原生实现,不依赖任何前端框架
- ajax动态加载支持图片懒加载
- 支持图片缓存到本地
- 轻量模块化
如何使用
- 引入md5.min.js,因为依赖js版md5函数,用于将图片url转换为32位md5
<script src="md5.min.js"></script>
-
在头部js包含下面的
lazyload
方法函数,否则可能报错函数未定义 -
HTML代码使用ajax动态生成如下img标签,src为默认图片,data-src填写图片网络地址,并且必须包含onload事件来触发懒加载功能。
<img src="placehold.jpg" data-lazyload="http://...jpg" onload="lazyload(this)" />
注意:因为函数依赖plus.io和plus.downloader接口,所以在plus还没ready的时候img onload执行lazyload可能会报错,lazyload比plus先执行完毕。
当然,在真实环境中,不管是商品列表、订单列表等,我们的图片一般都是动态加载的,所以问题不大。 在代码的写法策略上需要使用动态加载方式,尽量不使用写死在html里面。
- 添加.img-lazyload 支持图片淡入样式
@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}
@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}
.img-lazyload{-webkit-animation: fadeIn 350ms linear 0ms 1 normal both;animation: fadeIn 350ms linear 0ms 1 normal both;opacity:1;}
- 图片默认缓存到
_downloads/image/
目录下
函数源代码
/**
* 图片懒加载
* @param {Object} obj DOMElement
* @param {Function} callback 加载完成回调函数
*
* @author fanrong33
* @version 1.1.0 build 20160107
*/
function lazyload(obj, callback){
var debug = false; // 默认打印调试日志
if(obj.getAttribute('data-loaded')){
return;
}
var image_url = obj.getAttribute('data-lazyload');
debug && console.log(image_url);
// 1. 转换网络图片地址为本地缓存图片路径,判断该图片是否存在本地缓存
// http://...jpg -> md5
// 缓存目录 _downloads/image/(md5).jpg
var image_md5 = md5(image_url);
var local_image_url = '_downloads/image/'+image_md5+'.jpg'; // 缓存本地图片url
var absolute_image_path = plus.io.convertLocalFileSystemURL(local_image_url); // 平台绝对路径
// new temp_img 用于判断图片文件是否存在
var temp_img = new Image();
temp_img.src = absolute_image_path;
temp_img.onload = function(){
debug && console.log('存在本地缓存图片文件'+local_image_url+',直接显示');
// 1.1 存在,则直接显示(本地已缓存,不需要淡入动画)
obj.setAttribute('src', absolute_image_path);
obj.setAttribute('data-loaded', true);
obj.classList.add('img-lazyload');
callback && callback();
return;
}
temp_img.onerror = function(){
debug && console.log('不存在本地缓存图片文件');
// 1.2 下载图片缓存到本地
debug && console.log('开始下载图片'+image_url+' 缓存到本地: '+local_image_url);
function download_img(){
var download_task = plus.downloader.createDownload(image_url, {
filename: local_image_url // filename:下载任务在本地保存的文件路径
}, function(download, status) {
if(status != 200){
// 下载失败,删除本地临时文件
debug && console.log('下载失败,status'+status);
if(local_image_url != null){
plus.io.resolveLocalFileSystemURL(local_image_url, function(entry) {
entry.remove(function(entry) {
debug && console.log("临时文件删除成功" + local_image_url);
// 重新下载图片
download_img();
}, function(e) {
debug && console.log("临时文件删除失败" + local_image_url);
});
});
}
}else{
// 把下载成功的图片显示
// 将本地URL路径转换成平台绝对路径
obj.setAttribute('src', plus.io.convertLocalFileSystemURL(local_image_url));
obj.setAttribute('data-loaded', true);
obj.classList.add('img-lazyload');
callback && callback();
}
});
download_task.start();
}
download_img();
}
}
在uni-app中实现基于plus.downloader
的图片懒加载功能并支持本地缓存,可以显著提升应用的性能和用户体验。下面是一个简单的代码案例,展示了如何实现这一功能。
首先,确保你的项目中已经启用了5+ App(HBuilderX)的扩展API,并且已经配置了相关权限。
1. 创建图片懒加载组件
创建一个名为LazyLoadImage.vue
的组件,用于封装懒加载逻辑。
<template>
<view>
<image v-if="imageSrc" :src="imageSrc" @load="onLoad" @error="onError"></image>
<view v-else class="placeholder"></view>
</view>
</template>
<script>
export default {
props: {
src: {
type: String,
required: true
}
},
data() {
return {
imageSrc: ''
};
},
mounted() {
this.loadImage();
},
methods: {
loadImage() {
const localPath = `_doc/${this.hashCode(this.src)}`;
plus.io.resolveLocalFileSystemURL(localPath, entry => {
entry.file(file => {
this.imageSrc = file.toLocalURL();
}, err => {
this.downloadImage(this.src, localPath);
});
}, err => {
this.downloadImage(this.src, localPath);
});
},
downloadImage(url, localPath) {
const task = plus.downloader.createDownload(url, {
filename: localPath
}, (d, status) => {
if (status === 200) {
this.imageSrc = d.target.url;
} else {
console.error('Download failed: ' + status);
}
});
task.start();
},
hashCode(str) {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = hash * 31 + str.charCodeAt(i);
hash |= 0; // Convert to 32bit integer
}
return hash.toString(36);
},
onLoad() {
// Handle image load event if needed
},
onError() {
// Handle image error event if needed
}
}
};
</script>
<style scoped>
.placeholder {
width: 100%;
height: 200px; /* Adjust as needed */
background-color: #f0f0f0;
}
</style>
2. 使用懒加载组件
在你的页面中引入并使用这个组件:
<template>
<view>
<LazyLoadImage src="https://example.com/image.jpg"></LazyLoadImage>
</view>
</template>
<script>
import LazyLoadImage from '@/components/LazyLoadImage.vue';
export default {
components: {
LazyLoadImage
}
};
</script>
这个示例展示了如何基于plus.downloader
实现图片懒加载并支持本地缓存。LazyLoadImage
组件在挂载时检查本地是否存在缓存的图片,如果不存在则进行下载并缓存。注意,这里的hashCode
方法用于生成唯一的文件名,以避免文件名冲突。你可以根据实际需求调整这个逻辑。