微信小程序中如何实现图片的懒加载,并封装图片懒加载组件

angrybird2332023-09-01Frontend性能优化小程序

原理

  • 监听元素在小程序页面中的位置,及监听元素是否与页面相交相交,当元素与底部相交时,才加载图片。主要利用了小程序的wx.createIntersectionObserver() .relativeToViewport().observe()来实现的,点击查看文档地址open in new window

具体实现

wxml文件

<image 
  class="lazy-image image-class"
  src="{{ url }}" 
  wx:if="{{ url }}" 
  mode="{{ mode }}" 
  bindload="onImageLoad"
  bindtap="previewImage"
  style="opacity: {{opacity }}">
</image>
<view class="image-loading image-class" wx:if="{{ !url }}">
  <text class="loading-text">加载中...</text>
</view>

js文件


Component({
  externalClasses: ['image-class'],
  properties: {
    src: {
      type: String,
      value: '',
    },
    mode: {
      type: String,
      value: 'aspectFill',
    },
    preview_list: {
      type: Array,
      value: [],
    },
  },
  ready() {
    this.checkInView()
  },
  detached() {
    this.createIntersectionObserver().disconnect()
  },
  data: {
    url: '',
    opacity: 0,
    in_view: false,
  },

  methods: {
    // 检测是否在可视区域
    checkInView() {
      const { src, in_view } = this.data
      this.createIntersectionObserver()
        .relativeToViewport()
        .observe('.image-loading', ret => {
          if (ret.intersectionRatio && !in_view) {
            this.data.in_view = true
            this.setData({ url: src })
          }
        })
    },
    // 图片加载完成
    onImageLoad() {
      this.setData({
        opacity: 1,
      })
    },
    previewImage() {
      const { in_view, url, preview_list } = this.data
      if (!in_view || !url) return
      if (preview_list.length) {
        const urls = preview_list.map(item => item.url || item)
        wx.previewImage({
          current: url,
          urls: urls,
        })
      } else {
        wx.previewImage({
          current: url,
          urls: [url],
        })
      }
    },
  },
})

scss样式文件

.lazy-image {
  width: 100%;
  height: 100%;
  transition: opacity 0.5s ease-in-out;
}

.loading-container {
  width: 100%;
  height: 100%;
  background: #f7f7f7;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;

  .loading-text {
    color: #ccc;
    font-size: 14px;
  }
}

使用示例

json文件

{
  "usingComponents": {
    "lazy-image": "../lazy-image/lazy-image"
  }
}

<lazy-image image-class="img" src="{{ url }}" />
最后更新时间 1/7/2025, 6:24:06 AM