useScroll.ts 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. import type { Ref } from 'vue'
  2. import { onMounted, onUnmounted, ref, watch } from 'vue'
  3. import { useThrottleFn } from '@vueuse/core'
  4. import { isObject, isWindow } from '@/utils/is'
  5. export function useScroll(
  6. refEl: Ref<Element | Window | null>,
  7. options?: {
  8. wait?: number
  9. leading?: boolean
  10. trailing?: boolean
  11. },
  12. ) {
  13. const refX = ref(0)
  14. const refY = ref(0)
  15. let handler = () => {
  16. if (isWindow(refEl.value)) {
  17. refX.value = refEl.value.scrollX
  18. refY.value = refEl.value.scrollY
  19. }
  20. else if (refEl.value) {
  21. refX.value = (refEl.value).scrollLeft
  22. refY.value = (refEl.value).scrollTop
  23. }
  24. }
  25. if (isObject(options)) {
  26. let wait = 0
  27. if (options.wait && options.wait > 0) {
  28. wait = options.wait
  29. Reflect.deleteProperty(options, 'wait')
  30. }
  31. handler = useThrottleFn(handler, wait)
  32. }
  33. let stopWatch: () => void
  34. onMounted(() => {
  35. stopWatch = watch(
  36. refEl,
  37. (el, prevEl, onCleanup) => {
  38. if (el)
  39. el.addEventListener('scroll', handler)
  40. else if (prevEl)
  41. prevEl.removeEventListener('scroll', handler)
  42. onCleanup(() => {
  43. refX.value = refY.value = 0
  44. el && el.removeEventListener('scroll', handler)
  45. })
  46. },
  47. { immediate: true },
  48. )
  49. })
  50. onUnmounted(() => {
  51. refEl.value && refEl.value.removeEventListener('scroll', handler)
  52. })
  53. function stop() {
  54. stopWatch && stopWatch()
  55. }
  56. return { refX, refY, stop }
  57. }