+
102
-

回答

我们需要自定义一个组件,实现根据src从本地缓冲中获取数据,没有缓冲就下载。

微信小程序提供了 wx.setStorage 和 wx.getStorage 来存储数据,以及 wx.saveFile 来保存文件。下面是一个适用于微信小程序的图片缓存组件:

<!-- components/cached-image/cached-image.wxml -->
<image
  src="{{imageSrc}}"
  mode="{{mode}}"
  lazy-load="{{lazyLoad}}"
  show-menu-by-longpress="{{showMenuByLongpress}}"
  binderror="onImageError"
  bindload="onImageLoad"
></image>
// components/cached-image/cached-image.js
Component({
  properties: {
    src: {
      type: String,
      observer: function(newVal) {
        this.loadImage(newVal);
      }
    },
    mode: {
      type: String,
      value: 'aspectFill'
    },
    lazyLoad: {
      type: Boolean,
      value: false
    },
    showMenuByLongpress: {
      type: Boolean,
      value: false
    }
  },

  data: {
    imageSrc: ''
  },

  methods: {
    async loadImage(url) {
      if (!url) return;

      try {
        // 检查缓存
        const cachedPath = await this.getCachedImage(url);
        if (cachedPath) {
          this.setData({ imageSrc: cachedPath });
          return;
        }

        // 下载并缓存图片
        const downloadRes = await this.downloadImage(url);
        const savedFilePath = await this.saveFile(downloadRes.tempFilePath);
        await this.cacheImage(url, savedFilePath);
        this.setData({ imageSrc: savedFilePath });
      } catch (error) {
        console.error('Failed to load image:', error);
        this.setData({ imageSrc: url }); // 如果失败,使用原始 URL
      }
    },

    getCachedImage(url) {
      return new Promise((resolve) => {
        wx.getStorage({
          key: url,
          success: (res) => {
            // 检查文件是否存在
            wx.getSavedFileInfo({
              filePath: res.data,
              success: () => resolve(res.data),
              fail: () => {
                // 如果文件不存在,删除存储的键
                wx.removeStorage({ key: url });
                resolve(null);
              }
            });
          },
          fail: () => resolve(null)
        });
      });
    },

    downloadImage(url) {
      return new Promise((resolve, reject) => {
        wx.downloadFile({
          url: url,
          success: resolve,
          fail: reject
        });
      });
    },

    saveFile(tempFilePath) {
      return new Promise((resolve, reject) => {
        wx.saveFile({
          tempFilePath: tempFilePath,
          success: (res) => resolve(res.savedFilePath),
          fail: reject
        });
      });
    },

    cacheImage(url, filePath) {
      return new Promise((resolve, reject) => {
        wx.setStorage({
          key: url,
          data: filePath,
          success: resolve,
          fail: reject
        });
      });
    },

    onImageError(e) {
      this.triggerEvent('error', e.detail);
    },

    onImageLoad(e) {
      this.triggerEvent('load', e.detail);
    }
  }
});

使用这个组件的方法:

<!-- pages/index/index.wxml -->
<cached-image
  src="https://example.com/image.jpg"
  mode="aspectFit"
  lazy-load="{{true}}"
  bind:error="handleImageError"
  bind:load="handleImageLoad"
></cached-image>
// pages/index/index.js
Page({
  handleImageError(e) {
    console.error('Image failed to load', e);
  },
  handleImageLoad(e) {
    console.log('Image loaded successfully', e);
  }
});

这个微信小程序版本的缓存图片组件有以下特点:

使用 wx.setStorage 和 wx.getStorage 来存储图片URL和本地文件路径的映射。使用 wx.saveFile 来将下载的临时文件保存为永久文件。在检查缓存时,会验证缓存的文件是否仍然存在。如果缓存的文件不存在,会删除相应的存储键。如果图片加载失败,会回退到使用原始URL。支持 error 和 load 事件,与原生 image 组件保持一致。

注意事项:

微信小程序有存储限制,通常为10MB。您可能需要实现一个缓存清理机制,以防止超出存储限制。

wx.saveFile 保存的文件会持久保存在本地,直到用户清除微信存储或小程序被删除。您可能需要定期清理旧的缓存文件。

这个组件主要适用于需要频繁加载的小型图片。对于大型图片或不常更改的图片,可能需要不同的策略。

在实际应用中,您可能还需要添加更多的错误处理和边界情况检查。

网友回复

我知道答案,我要回答