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)))
}

 

posted @ 2025-03-03 18:13  wjs0509  阅读(76)  评论(0)    收藏  举报