mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-08-26 08:36:19 +08:00
chore: 优化 useScrollTo、useWindowSizeFn
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
export * from './onMountedOrActivated';
|
||||
export * from './useAttrs';
|
||||
export * from './useRefs';
|
||||
export * from './useScrollTo';
|
||||
export * from './useWindowSizeFn';
|
||||
export { useTimeoutFn } from '@vueuse/core';
|
||||
|
@@ -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 };
|
||||
|
@@ -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 };
|
||||
|
60
packages/hooks/src/useScrollTo.ts
Normal file
60
packages/hooks/src/useScrollTo.ts
Normal 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 };
|
40
packages/hooks/src/useWindowSizeFn.ts
Normal file
40
packages/hooks/src/useWindowSizeFn.ts
Normal 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 };
|
Reference in New Issue
Block a user