chore: 优化 useScrollTo、useWindowSizeFn

This commit is contained in:
vben
2023-04-07 00:12:26 +08:00
parent 6a9bd686d5
commit 335f30c887
17 changed files with 69 additions and 47 deletions

View File

@@ -1,4 +1,6 @@
export * from './onMountedOrActivated';
export * from './useAttrs';
export * from './useRefs';
export * from './useScrollTo';
export * from './useWindowSizeFn';
export { useTimeoutFn } from '@vueuse/core';

View File

@@ -1,7 +1,7 @@
import { type Recordable } from '@vben/types';
import { getCurrentInstance, reactive, shallowRef, watchEffect } from 'vue';
interface Options {
interface UseAttrsOptions {
excludeListeners?: boolean;
excludeKeys?: string[];
excludeDefaultKeys?: boolean;
@@ -14,7 +14,7 @@ function entries<T>(obj: Recordable<T>): [string, T][] {
return Object.keys(obj).map((key: string) => [key, obj[key]]);
}
function useAttrs(options: Options = {}): Recordable<any> {
function useAttrs(options: UseAttrsOptions = {}): Recordable<any> {
const instance = getCurrentInstance();
if (!instance) return {};
@@ -40,4 +40,4 @@ function useAttrs(options: Options = {}): Recordable<any> {
return attrs;
}
export { useAttrs };
export { useAttrs, type UseAttrsOptions };

View File

@@ -1,7 +1,10 @@
import type { Ref } from 'vue';
import { onBeforeUpdate, shallowRef } from 'vue';
export function useRefs(): [Ref<HTMLElement[]>, (index: number) => (el: HTMLElement) => void] {
function useRefs(): {
refs: Ref<HTMLElement[]>;
setRefs: (index: number) => (el: HTMLElement) => void;
} {
const refs = shallowRef([]) as Ref<HTMLElement[]>;
onBeforeUpdate(() => {
@@ -12,5 +15,10 @@ export function useRefs(): [Ref<HTMLElement[]>, (index: number) => (el: HTMLElem
refs.value[index] = el;
};
return [refs, setRefs];
return {
refs,
setRefs,
};
}
export { useRefs };

View File

@@ -0,0 +1,60 @@
import { shallowRef, unref } from 'vue';
interface UseScrollToOptions {
el: any;
to: number;
duration?: number;
callback?: () => any;
}
function easeInOutQuad(t: number, b: number, c: number, d: number) {
t /= d / 2;
if (t < 1) {
return (c / 2) * t * t + b;
}
t--;
return (-c / 2) * (t * (t - 2) - 1) + b;
}
function move(el: HTMLElement, amount: number) {
el.scrollTop = amount;
}
const position = (el: HTMLElement) => {
return el.scrollTop;
};
function useScrollTo({ el, to, duration = 500, callback }: UseScrollToOptions) {
const isActiveRef = shallowRef(false);
const start = position(el);
const change = to - start;
const increment = 20;
let currentTime = 0;
const animateScroll = function () {
if (!unref(isActiveRef)) {
return;
}
currentTime += increment;
const val = easeInOutQuad(currentTime, start, change, duration);
move(el, val);
if (currentTime < duration && unref(isActiveRef)) {
requestAnimationFrame(animateScroll);
} else {
if (callback && typeof callback === 'function') {
callback();
}
}
};
const run = () => {
isActiveRef.value = true;
animateScroll();
};
const stop = () => {
isActiveRef.value = false;
};
return { start: run, stop };
}
export { useScrollTo, type UseScrollToOptions };

View File

@@ -0,0 +1,40 @@
import { type AnyFunction } from '@vben/types';
import { tryOnMounted, tryOnUnmounted, useDebounceFn } from '@vueuse/core';
interface UseWindowSizeOptions {
wait?: number;
once?: boolean;
immediate?: boolean;
listenerOptions?: AddEventListenerOptions | boolean;
}
function useWindowSizeFn(fn: AnyFunction, options: UseWindowSizeOptions = {}) {
const { wait = 150, immediate } = options;
let handler = () => {
fn();
};
const handleSize = useDebounceFn(handler, wait);
handler = handleSize;
const start = () => {
if (immediate) {
handler();
}
window.addEventListener('resize', handler);
};
const stop = () => {
window.removeEventListener('resize', handler);
};
tryOnMounted(() => {
start();
});
tryOnUnmounted(() => {
stop();
});
return { start, stop };
}
export { useWindowSizeFn, type UseWindowSizeOptions };