From bc6c3425c7f9b5fc64a9854b46a9b6fc91700430 Mon Sep 17 00:00:00 2001 From: webfansplz <308241863@qq.com> Date: Fri, 17 Sep 2021 15:19:03 +0800 Subject: [PATCH] feat(useScroll): new Function (#739) Co-authored-by: webfansplz <> Co-authored-by: Anthony Fu --- indexes.json | 7 ++ packages/core/index.ts | 1 + packages/core/useScroll/demo.vue | 56 +++++++++++++++ packages/core/useScroll/index.md | 22 ++++++ packages/core/useScroll/index.ts | 117 +++++++++++++++++++++++++++++++ packages/functions.md | 1 + 6 files changed, 204 insertions(+) create mode 100644 packages/core/useScroll/demo.vue create mode 100644 packages/core/useScroll/index.md create mode 100644 packages/core/useScroll/index.ts diff --git a/indexes.json b/indexes.json index 452d5aa2879a..2d883f75c057 100644 --- a/indexes.json +++ b/indexes.json @@ -874,6 +874,13 @@ "category": "Browser", "description": "script tag injecting" }, + { + "name": "useScroll", + "package": "core", + "docs": "https://vueuse.org/core/useScroll/", + "category": "Sensors", + "description": "reactive scroll position and state" + }, { "name": "useSessionStorage", "package": "core", diff --git a/packages/core/index.ts b/packages/core/index.ts index bd7869a5d0ef..a84c7de0947e 100644 --- a/packages/core/index.ts +++ b/packages/core/index.ts @@ -58,6 +58,7 @@ export * from './useRafFn' export * from './useRefHistory' export * from './useResizeObserver' export * from './useScriptTag' +export * from './useScroll' export * from './useSessionStorage' export * from './useShare' export * from './useSpeechRecognition' diff --git a/packages/core/useScroll/demo.vue b/packages/core/useScroll/demo.vue new file mode 100644 index 000000000000..aa0c8860b02e --- /dev/null +++ b/packages/core/useScroll/demo.vue @@ -0,0 +1,56 @@ + + + diff --git a/packages/core/useScroll/index.md b/packages/core/useScroll/index.md new file mode 100644 index 000000000000..0ee251ab2db5 --- /dev/null +++ b/packages/core/useScroll/index.md @@ -0,0 +1,22 @@ +--- +category: Sensors +--- + +# useScroll + +Reactive scroll position and state + +## Usage + +```html + + + +``` diff --git a/packages/core/useScroll/index.ts b/packages/core/useScroll/index.ts new file mode 100644 index 000000000000..72e29d480f07 --- /dev/null +++ b/packages/core/useScroll/index.ts @@ -0,0 +1,117 @@ +import { ref, reactive } from 'vue-demi' +import { useThrottleFn, useDebounceFn, noop, MaybeRef } from '@vueuse/shared' +import { useEventListener } from '../useEventListener' + +export interface UseScrollOptions { + /** + * Throttle time for scroll event,it’s disabled by default. + * + * @default 0 + */ + throttle?: number + + /** + * The check time when scrolling ends. + * This configuration will be setting to (throttle + idle) when the `throttle` is configured. + * + * @default 200 + */ + idle?: number + + /** + * Trigger it when scrolling. + * + */ + onScroll?: () => void + + /** + * Trigger it when scrolling ends. + * + */ + onStop?: () => void + + /** + * Listener options for scroll event. + * + * @default {capture: false, passive: true} + */ + eventListenerOptions?: boolean | AddEventListenerOptions +} + +/** + * Reactive scroll. + * + * @see https://vueuse.org/useScroll + * @param element + * @param options + */ + +export function useScroll( + element: MaybeRef, + options: UseScrollOptions = {}, +) { + const { + throttle = 0, + idle = 200, + onStop = noop, + onScroll = noop, + eventListenerOptions = { + capture: false, + passive: true, + }, + } + = options + + const x = ref(0) + const y = ref(0) + const isScrolling = ref(false) + const arrivedState = reactive({ + left: true, + right: false, + top: true, + bottom: false, + }) + + if (element) { + const onScrollEnd = useDebounceFn(() => { + isScrolling.value = false + onStop() + }, throttle + idle) + + const onScrollHandler = (e: Event) => { + const eventTarget = (e.target === document ? (e.target as Document).documentElement : e.target) as HTMLElement + + const scrollLeft = eventTarget.scrollLeft + arrivedState.left = scrollLeft <= 0 + arrivedState.right = scrollLeft + eventTarget.clientWidth >= eventTarget.scrollWidth + x.value = scrollLeft + + const scrollTop = eventTarget.scrollTop + arrivedState.top = scrollTop <= 0 + arrivedState.bottom = scrollTop + eventTarget.clientHeight >= eventTarget.scrollHeight + y.value = scrollTop + + isScrolling.value = true + onScrollEnd() + onScroll() + } + + useEventListener( + element, + 'scroll', + throttle + ? useThrottleFn(onScrollHandler, throttle) + : onScrollHandler, + eventListenerOptions, + ) + } + + return { + x, + y, + isScrolling, + arrivedState, + } +} + +export type UseScrollReturn = ReturnType diff --git a/packages/functions.md b/packages/functions.md index bd643a301716..95b2be6b0745 100644 --- a/packages/functions.md +++ b/packages/functions.md @@ -90,6 +90,7 @@ - [`usePointer`](https://vueuse.org/core/usePointer/) — reactive [pointer state](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events) - [`usePointerSwipe`](https://vueuse.org/core/usePointerSwipe/) — reactive swipe detection based on [PointerEvents](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent) - [`useResizeObserver`](https://vueuse.org/core/useResizeObserver/) — reports changes to the dimensions of an Element's content or the border-box + - [`useScroll`](https://vueuse.org/core/useScroll/) — reactive scroll position and state - [`useSpeechRecognition`](https://vueuse.org/core/useSpeechRecognition/) — reactive [SpeechRecognition](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition) - [`useSwipe`](https://vueuse.org/core/useSwipe/) — reactive swipe detection based on [`TouchEvents`](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent) - [`useUserMedia`](https://vueuse.org/core/useUserMedia/) — reactive [`mediaDevices.getUserMedia`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia) streaming