vue3 触底加载hooks
import { onUnmounted, ref } from 'vue' /** * onReachBottomFn :滚动加载函数 * reachBottomDistance : 距离底部多少距离时触发 */ function useScrollBottom(onReachBottomFn, reachBottomDistance = 100) { const isReachBottom = ref(false) let scrollListenerAttached = false let elementRef = null let moreQueryParams = ref({}) const onScroll = async () => { if (elementRef) { const scrollTop = elementRef.scrollTop const scrollHeight = elementRef.scrollHeight const clientHeight = elementRef.clientHeight const currentHeight = scrollTop + clientHeight const isAtBottom = currentHeight + reachBottomDistance >= scrollHeight if (isAtBottom && !isReachBottom.value) { // 调用传入的触底触发函数 bool 值代表是否还有更多数据 const isEnd = await onReachBottomFn(moreQueryParams.value) isReachBottom.value = isEnd } } } const attachScrollListener = async (ele) => { elementRef = ele if (elementRef && !scrollListenerAttached) { elementRef.addEventListener('scroll', onScroll) scrollListenerAttached = true // 默认触发一次分页接口 await onReachBottomFn(moreQueryParams.value) } } const clearListener = () => { if (elementRef) { elementRef.removeEventListener('scroll', onScroll) } } const updateQuery = (newQuery) => { moreQueryParams.value = newQuery } onUnmounted(() => { clearListener() }) return { isReachBottom, attachScrollListener, updateQuery } } export default useScrollBottom
使用:
const { isReachBottom, attachScrollListener, updateQuery } = useScrollBottom(getDataFn, 30) onMounted(() => { attachScrollListener(listRef.value) }) const getDataFn = async () => { pageNum.value++ loading.value = true const res = await fn({ currentPage: pageNum.value, pageSize: pageSize.value, orderBoardModuleToDealType: orderBoardModuleToDealType.value }) loading.value = false if (res.data?.length) { contentList.value = [...contentList.value, ...res.data] } return new Promise((c) => c(pageNum.value * pageSize.value >= Number(res?.data?.total))) }