在开发过程中如果有遇到滚动加载的需求,使用[IntersectionObserver] API (developer.mozilla.org/zh-CN/docs/…) 是一个非常不错的方案。IntersectionObserver有两个重要的点,一个的根元素(默认为视口),一个为交叉元素,废话不多说,我们直接上代码。
<template>
<div class="">
<ul class="list">
<li v-for="(item, index) in data" :key="index">
{{ item }}
</li>
<li class="loading">loading...</li>
</ul>
</div>
</template>
<template>
<div class="">
<ul class="list">
<li v-for="(item, index) in data" :key="index">
{{ item }}
</li>
<li class="loading">loading...</li>
</ul>
</div>
</template>
<script lang="ts" setup>
const data = ref([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
let ob = null
onMounted(() => {
const list = document.querySelector(".list")
const loading = document.querySelector(".loading")
ob = new IntersectionObserver(function (entries) {
const entry = entries[0]
if (!entry.isIntersecting) {
// 如果没有交叉 直接return
return
}
// 该例交叉后去调loadMore方法(模拟接口返回数据) 实际根据自己场景去写业务
loadMore()
}, {
root: list, // 和谁交叉 默认为视口 该demo为 loading类 和 list类交叉
threshold: 1 // 阈值:0~1 即loading出现在list的比列,设置为1即完全暴露
})
ob.observe(loading as HTMLElement) // 观察交叉的元素
})
async function loadMore() {
setTimeout(() => {
for (let index = 0; index < 10; index++) {
data.value.push(index)
}
}, 300)
}
onUnmounted(() => {
// 卸载实例,避免不必要的资源浪费
ob!.unobserve(document.querySelector(".loading"))
})
</script>
<style scoped>
.list {
height: 150px;
overflow: auto;
background-color: antiquewhite;
}
</style>
以上是PC端的一个简单例子,当然它还有更多的属性可供使用,想了解可查看MDN,
接下来介绍一下小程序端关于该API的使用,由于uniapp和微信小程序并不支持该API的使用,不过官方也是有提供类似的API来供使用,下面我们以uniapp来做例子:
<template>
<view>
<scroll-view scroll-y="true" class="list">
<view class="list-item" v-for="(item,i) in list" :key="i">
{{item}}
</view>
<view class="load">
我是一个Loading
</view>
</scroll-view>
</view>
</template>
<script>
export default {
data() {
return {
_observer: null,
list: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}
},
onReady() {
},
onLoad() {
// 第一个参数传入组件this
this._observer = uni.createIntersectionObserver(this, {
thresholds: 1, // 阈值:0~1
})
this._observer
.relativeTo('.list', {
bottom: 10 // bottom:10表示 load类进入 list类区域以下的10px就会触发 设置为0即交叉触发 (top/left/right同理)
})
.observe('.load', async (res) => {
// 交叉后的回调
// intersectionRatio 相交比列,由于滚动的时候加载完成数据intersectionRatio会变为0,为了防止再次调用loadMore,可以利用intersectionRatio的值作为条件
if (res.intersectionRatio > 0) {
await this.loadMore()
}
})
},
onUnload() {
if (this._observer) this._observer = null
},
methods: {
loadMore() {
setTimeout(() => {
for (let index = 0; index < 10; index++) {
this.list.push(index)
}
}, 300)
}
}
}
</script>
<style>
.list {
padding-left: 40rpx;
box-sizing: border-box;
height: 240px;
border: 1px solid;
}
.list-item {
height: 40px;
line-height: 40px;
}
</style>
以上就是uniapp关于该API的使用,微信小程序为wx.createIntersectionObserver(),用法同理。 谢谢您的观看,如有帮助,关注+点赞+收藏。如有问题,欢迎指正。