uni-app分享基于plus.downloader的图片懒加载功能,支持本地缓存v1.1.0

发布于 1周前 作者 sinazl 来自 Uni-App

uni-app分享基于plus.downloader的图片懒加载功能,支持本地缓存v1.1.0

今天试用了下hello mui上的图片懒加载功能,发现有些地方还无法满足我的需求,ajax动态加载的时候无法实现懒加载。

然后又看了下36kr的示例,因为代码关系实在太多了,耦合度比较高,遂自己动手写了一个轻量级的懒加载功能模块,而且支持图片缓存到本地哦~~~

欢迎各位拍砖,交流碰撞思想!

升级日志

v1.1.0 build 20160107

  1. 已增加 @LFZ 的代码,不用重复下载两次服务器端的图片
  2. 新增图片加载淡入特效
  3. 新增图片加载完成后回调
  4. 修改data-src为data-lazyload

图片

功能特性

  • 原生实现,不依赖任何前端框架
  • ajax动态加载支持图片懒加载
  • 支持图片缓存到本地
  • 轻量模块化

如何使用

  1. 引入md5.min.js,因为依赖js版md5函数,用于将图片url转换为32位md5
<script src="md5.min.js"></script>
  1. 在头部js包含下面的lazyload方法函数,否则可能报错函数未定义

  2. 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里面。

  1. 添加.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;}
  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();
    }
}

1 回复

在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方法用于生成唯一的文件名,以避免文件名冲突。你可以根据实际需求调整这个逻辑。

回到顶部