vue3 demo 实例:
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { notification } from 'ant-design-vue'
const scrollRef = ref()
type ListDataType = { label: string, value: string }
// 初始化数据
const initData = (): ListDataType[] => {
const data: ListDataType[] = [];
for (let i = 1; i < 50; ++i) {
data.push({
label: `label${i}`,
value: `label${i}`,
})
}
return data
};
// state
const state: any = reactive({
listData: initData()
})
// 重置
const resetData = () => {
state.listData = initData()
};
//追加数据
const appendData = () => {
const data: any = [];
const length = state.listData.length
for (let i = length + 1; i < 10 + length; ++i) {
data.push({
label: `label${i}`,
value: `label${i}`,
})
}
state.listData = [...state.listData, ...data]
}
//滚动事件
const scrollEvent = (e: any) => {
console.log('e', e)
// 不使用滚动条的情况下为了适应视口中所用内容所需的最小高度
const scrollHeight = e.target.scrollHeight
// 从其顶部边缘滚动的像素数
const scrollTop = e.target.scrollTop
// dom 视口高度(不包含任何滚动条)
const clientHeight = e.target.clientHeight
console.log('scrollTop', scrollTop)
console.log('clientHeight', clientHeight)
console.log('scrollHeight', scrollHeight)
// 向上取整
if (Math.ceil(scrollTop + clientHeight + 1) >= scrollHeight) {
notification.open({
message: '到底啦!',
})
appendData()
}
}
//监听 dom滚动
const listenDomScroll = () => {
try {
if (scrollRef.value) {
//@ts-ignore
scrollRef.value.removeEventListener('scroll', scrollEvent)
scrollRef.value.addEventListener('scroll', scrollEvent)
}
}
catch (e) {
console.error(e)
}
};
// 初始化页面
onMounted(() => {
listenDomScroll()
})
</script>
<template>
<div>
<a-button type="primary" @click="resetData">重置</a-button>
<div style="max-height:300px;overflow-y:auto;width:200px" ref="scrollRef">
<div v-for="item in state.listData" :key="item.value"
style="background:#0052d9;color:#fff;padding:2px;margin:2px;">
{{ item.label }}
</div>
</div>
</div>
</template>
效果:
代码块inscode