微信小程序中如何实现图片的懒加载,并封装图片懒加载组件
原理
- 监听元素在小程序页面中的位置,及监听元素是否与页面相交相交,当元素与底部相交时,才加载图片。主要利用了小程序的wx.createIntersectionObserver() .relativeToViewport().observe()来实现的,点击查看文档地址
具体实现
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 }}" />