项目:taro3+vue3
描述:图片懒加载通过滚动距离的计算进行加载,这里记录下用createIntersectionObserver来实现
createIntersectionObserver介绍任意门
原理比较简单,通过监听图片,出现在显示区域内就渲染图片,透明度0,图片加载完成后透明度为1,这样就有个过度效果,加载失败显示一个失败的,也可以再加个图片loading的效果,这里直接在容器上设置的背景色代替了
<view
class="base-lazy-image"
:id="`base-lazy-image-${index}`">
<image
v-if="isShowImg"
class="img"
:class="{'active': !isOpacity}"
:src="url"
@load="onLoad"
@error="onError"></image>
<view
v-if="isShowError"
class="error">error</view>
</view>
.base-lazy-image {
position: relative;
width: 200px;
height: 200px;
background: red;
.img {
width: 100%;
height: 100%;
opacity: 0;
transition: opacity .5s;
&.active {
opacity: 1;
}
}
.error {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 10;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background-color: #f7f8fa;
color: #969799;
}
}
isShowImg = ref(false)
isOpacity = ref(true)
isShowError = ref(false)
observer = ref(null)
// 参数
props: {
url: {
type: String,
default: ''
},
index: {
type: Number,
default: 0
}
}
clear() {
if (this.observer.value) {
this.observer.value.disconnect()
}
this.observer.value = null
}
addObserver() {
let a = getCurrentInstance()
if (this.observer.value || this.isShowImg.value) {
return
}
const observer = Taro.createIntersectionObserver(a.page)
observer.relativeToViewport({ bottom: -10 })
.observe('#base-lazy-image-'+this.props.index, (res) => {
if (res.intersectionRatio > 0) {
this.isShowImg.value = true
this.clear()
}
})
this.observer.value = observer
}
watch(() => props.url, newVal => {
if (newVal) {
this.addObserver()
}
})
页面中使用:
<block v-for="(item, index) in fieldList">
<view
:id="`merchant-item-${index}`"
class="merchant-item f-l-c">
<base-lazy-image
:index="index"
:url="item.url"/>
<view class="con">
<view class="name">
名称-{{ index }}
</view>
</view>
</view>
</block>
async getList() {
// 获取列表
const list = await xxx.xxxx()
this.fieldList.value = list
setTimeout(() => {
for(let i = 0; i < this.fieldList.value.length; i++) {
this.fieldList.value[i].url = this.fieldList.value[i].homeImage
}
}, 1000)
}
注意点:
1、获取列表后要加个延时,要不然监听不到
2、组件里面是通过watch url去添加监听器,这个url必须有个赋值的过程,如果接口里面本来就是有url字段的,组件里面并不会去添加监听器
3、组件内监听的是id, 用index区分,监听到了结果后要断开监听,之前有试过监听 ‘.base-lazy-image’, 会全部展示出来