基于vue3.x手写的一个移动端异步加载下拉列表实现
<template>
<ul class="approve-list" ref="listRef">
<Card v-for="(item, index) in dataList" :key="index" :cardInfo="item"></Card>
<li class="bottom-hint">
<span>{{ bottomMessage }}</span>
</li>
</ul>
</template>
<script lang="ts" setup>
import axios from 'axios'
import { onMounted, reactive, toRefs, ref } from 'vue';
import Card from '../components/card.vue';
const data = reactive({
dataList: [],
total: 0,
param: {
pageNo: 1,
pageSize: 5
},
// 是否请求
isRequest: false,
bottomMessage: '暂无数据',
})
onMounted(() => {
initApproveList()
})
const initApproveList = async () => {
const params = {
accountName: null,
accountNo: null,
...data.param
}
data.bottomMessage = '加载中...'
const res = await axios.post('/api/account/accountList', params, {
headers: {
authorization: 'Basic ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnBZWFFpT2pFMk56TXhPREkwTmpRc0ltVjRjQ0k2TVRZM016RTVOamcyTkgwLjAteWF0X3RvenJHbmh5ZUYzMTRidWRaZGctVTZFWmtoYmxteFVXUktJZlU6'
}
})
if (res.data?.code === 0) {
let resData = res.data.data
let { total, list } = resData
data.dataList = data.dataList.concat(list)
data.total = total
data.isRequest = false
if (data.param.pageNo * data.param.pageSize >= total) data.bottomMessage = '已加载全部数据'
}
}
const listRef = ref()
window.addEventListener('scroll', () => {
let { isRequest, param, total } = data
const general = document.querySelector('.approve-list')
let momentHeight = general?.getBoundingClientRect().bottom || 0
console.log(general?.getBoundingClientRect().bottom, window.innerHeight);
isRequest = param.pageNo * param.pageSize >= total ? false : true
if (momentHeight <= window.innerHeight && isRequest){
setTimeout(() => {
data.param.pageNo++
initApproveList()
}, 1000)
}
})
const { dataList, total, bottomMessage } = toRefs(data)
</script>
<style lang="scss" scoped>
.approve-list {
// height: 100%;
margin: 0 auto;
padding: 0 15px;
list-style-type: none;
.bottom-hint {
font-size: 14px;
text-align: center;
height: 30px;
}
}
</style>
思路:当滚动条的高度小于或者等于可视区域高度时,即可异步获取数据,因为只是写了一个业务组件,没再进行简化,
下面这段为核心代码:
window.addEventListener('scroll', () => {
let { isRequest, param, total } = data
const general = document.querySelector('.approve-list')
let momentHeight = general?.getBoundingClientRect().bottom || 0
console.log(general?.getBoundingClientRect().bottom, window.innerHeight);
isRequest = param.pageNo * param.pageSize >= total ? false : true
if (momentHeight <= window.innerHeight && isRequest){
setTimeout(() => {
data.param.pageNo++
initApproveList()
}, 1000)
}
})
知识点- getBoundingClientRect()常用属性:
bottom:对象底部距离浏览器当前可视顶部的距离
height: 该对象的高度
left: 对象距离浏览器可视最左侧的距离
right: 对象距离浏览器可视最右侧的距离
Top: 对象顶部距离当前浏览器可视顶部的距离
width: 当前对象宽度
x: 对象左侧距离浏览器可视左侧距离
y: 对象顶部距离浏览器可视顶部水平