微信小程序提供了一个很好用的api,IntersectionObserver 对象,监听目标元素与其祖先或视窗交叉状态的手段。
其实现原理在于监听目标元素与参照区域相交(参照区域可以为页面显示区域、指定一个元素节点);
这里实现懒加载的原理就是如此,监听需要加载的图片,给图片数组添加一个showState:false的字段,当使用IntersectionObserver 监听到图片进入参照区域时,动态改变showState为true。
下面为代码:
wxml:
<view class="image-container">
<image wx:for="{{imageList}}" id="image_{{item.id}}" mode="widthFix" class="{{item.showState?'active':''}}" src="{{item.showState? item.src: ''}}" data-index="{{index}}"></image>
</view>
active为一个opacity:0到opacity:1的动画。
js部分:
//index.js
//获取应用实例
const app = getApp()
Page({
data: {
imageList: [
{ id: 1, src: "../../images/label_bookcase_01.png",showState: false },
{ id: 2, src: "../../images/label_bookshelf_01.png", showState: false },
{ id: 3, src: "../../images/label_classification_01.png", showState: false },
{ id: 4, src: "../../images/label_home_01.png", showState: false },
{ id: 5, src: "../../images/label_my_01.png", showState: false },
{ id: 6, src: "../../images/no_cover.png", showState: false },
]
},
onLoad: function(){
this.setViewportListener();
},
setViewportListener: function(){
let that = this;
for(let i = 0;i<that.data.imageList.length;i++){
const viewPort = wx.createIntersectionObserver().relativeToViewport();
viewPort.observe(`#image_${i}`, (res) => {
//console.log("图片进入视图区域", res);
let index = res.dataset.index;
let keyStr = `imageList[${index}].showState`;
that.setData({
[keyStr]: true
})
viewPort.disconnect();
})
}
}
})