mirror of
https://gitee.com/bootx/dax-pay-ui.git
synced 2025-09-04 03:16:02 +00:00
remove 国际化删除, 依赖精简
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { defineBuildConfig } from 'unbuild';
|
||||
import { defineBuildConfig } from 'unbuild'
|
||||
|
||||
export default defineBuildConfig({
|
||||
clean: true,
|
||||
@@ -7,4 +7,4 @@ export default defineBuildConfig({
|
||||
rollup: {
|
||||
emitCJS: true,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
@@ -1,7 +1,7 @@
|
||||
export * from './onMountedOrActivated';
|
||||
export * from './useAttrs';
|
||||
export * from './useRefs';
|
||||
export * from './useRequest';
|
||||
export * from './useScrollTo';
|
||||
export * from './useWindowSizeFn';
|
||||
export { useTimeoutFn } from '@vueuse/core';
|
||||
export * from './onMountedOrActivated'
|
||||
export * from './useAttrs'
|
||||
export * from './useRefs'
|
||||
export * from './useRequest'
|
||||
export * from './useScrollTo'
|
||||
export * from './useWindowSizeFn'
|
||||
export { useTimeoutFn } from '@vueuse/core'
|
||||
|
@@ -1,25 +1,25 @@
|
||||
import { type AnyFunction } from '@vben/types';
|
||||
import { nextTick, onActivated, onMounted } from 'vue';
|
||||
import { type AnyFunction } from '@vben/types'
|
||||
import { nextTick, onActivated, onMounted } from 'vue'
|
||||
|
||||
/**
|
||||
* 在 OnMounted 或者 OnActivated 时触发
|
||||
* @param hook 任何函数(包括异步函数)
|
||||
*/
|
||||
function onMountedOrActivated(hook: AnyFunction) {
|
||||
let mounted: boolean;
|
||||
let mounted: boolean
|
||||
|
||||
onMounted(() => {
|
||||
hook();
|
||||
hook()
|
||||
nextTick(() => {
|
||||
mounted = true;
|
||||
});
|
||||
});
|
||||
mounted = true
|
||||
})
|
||||
})
|
||||
|
||||
onActivated(() => {
|
||||
if (mounted) {
|
||||
hook();
|
||||
hook()
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
export { onMountedOrActivated };
|
||||
export { onMountedOrActivated }
|
||||
|
@@ -1,43 +1,43 @@
|
||||
import { type Recordable } from '@vben/types';
|
||||
import { getCurrentInstance, reactive, shallowRef, watchEffect } from 'vue';
|
||||
import { type Recordable } from '@vben/types'
|
||||
import { getCurrentInstance, reactive, shallowRef, watchEffect } from 'vue'
|
||||
|
||||
interface UseAttrsOptions {
|
||||
excludeListeners?: boolean;
|
||||
excludeKeys?: string[];
|
||||
excludeDefaultKeys?: boolean;
|
||||
excludeListeners?: boolean
|
||||
excludeKeys?: string[]
|
||||
excludeDefaultKeys?: boolean
|
||||
}
|
||||
|
||||
const DEFAULT_EXCLUDE_KEYS = ['class', 'style'];
|
||||
const LISTENER_PREFIX = /^on[A-Z]/;
|
||||
const DEFAULT_EXCLUDE_KEYS = ['class', 'style']
|
||||
const LISTENER_PREFIX = /^on[A-Z]/
|
||||
|
||||
function entries<T>(obj: Recordable<T>): [string, T][] {
|
||||
return Object.keys(obj).map((key: string) => [key, obj[key]]);
|
||||
return Object.keys(obj).map((key: string) => [key, obj[key]])
|
||||
}
|
||||
|
||||
function useAttrs(options: UseAttrsOptions = {}): Recordable<any> {
|
||||
const instance = getCurrentInstance();
|
||||
if (!instance) return {};
|
||||
const instance = getCurrentInstance()
|
||||
if (!instance) return {}
|
||||
|
||||
const { excludeListeners = false, excludeKeys = [], excludeDefaultKeys = true } = options;
|
||||
const attrs = shallowRef({});
|
||||
const allExcludeKeys = excludeKeys.concat(excludeDefaultKeys ? DEFAULT_EXCLUDE_KEYS : []);
|
||||
const { excludeListeners = false, excludeKeys = [], excludeDefaultKeys = true } = options
|
||||
const attrs = shallowRef({})
|
||||
const allExcludeKeys = excludeKeys.concat(excludeDefaultKeys ? DEFAULT_EXCLUDE_KEYS : [])
|
||||
|
||||
// Since attrs are not reactive, make it reactive instead of doing in `onUpdated` hook for better performance
|
||||
instance.attrs = reactive(instance.attrs);
|
||||
instance.attrs = reactive(instance.attrs)
|
||||
|
||||
watchEffect(() => {
|
||||
const res = entries(instance.attrs).reduce((acm, [key, val]) => {
|
||||
if (!allExcludeKeys.includes(key) && !(excludeListeners && LISTENER_PREFIX.test(key))) {
|
||||
acm[key] = val;
|
||||
acm[key] = val
|
||||
}
|
||||
|
||||
return acm;
|
||||
}, {} as Recordable<any>);
|
||||
return acm
|
||||
}, {} as Recordable<any>)
|
||||
|
||||
attrs.value = res;
|
||||
});
|
||||
attrs.value = res
|
||||
})
|
||||
|
||||
return attrs;
|
||||
return attrs
|
||||
}
|
||||
|
||||
export { useAttrs, type UseAttrsOptions };
|
||||
export { useAttrs, type UseAttrsOptions }
|
||||
|
@@ -1,24 +1,24 @@
|
||||
import type { ComponentPublicInstance, Ref } from 'vue';
|
||||
import { onBeforeUpdate, shallowRef } from 'vue';
|
||||
import type { ComponentPublicInstance, Ref } from 'vue'
|
||||
import { onBeforeUpdate, shallowRef } from 'vue'
|
||||
|
||||
function useRefs<T = HTMLElement>(): {
|
||||
refs: Ref<T[]>;
|
||||
setRefs: (index: number) => (el: Element | ComponentPublicInstance | null) => void;
|
||||
refs: Ref<T[]>
|
||||
setRefs: (index: number) => (el: Element | ComponentPublicInstance | null) => void
|
||||
} {
|
||||
const refs = shallowRef([]) as Ref<T[]>;
|
||||
const refs = shallowRef([]) as Ref<T[]>
|
||||
|
||||
onBeforeUpdate(() => {
|
||||
refs.value = [];
|
||||
});
|
||||
refs.value = []
|
||||
})
|
||||
|
||||
const setRefs = (index: number) => (el: Element | ComponentPublicInstance | null) => {
|
||||
refs.value[index] = el as T;
|
||||
};
|
||||
refs.value[index] = el as T
|
||||
}
|
||||
|
||||
return {
|
||||
refs,
|
||||
setRefs,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export { useRefs };
|
||||
export { useRefs }
|
||||
|
@@ -1,20 +1,20 @@
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
import { reactive } from 'vue';
|
||||
import { reactive } from 'vue'
|
||||
|
||||
import type { FetchState, PluginReturn, Service, Subscribe, UseRequestOptions } from './types';
|
||||
import { isFunction } from './utils/isFunction';
|
||||
import type { FetchState, PluginReturn, Service, Subscribe, UseRequestOptions } from './types'
|
||||
import { isFunction } from './utils/isFunction'
|
||||
|
||||
export default class Fetch<TData, TParams extends any[]> {
|
||||
pluginImpls: PluginReturn<TData, TParams>[] = [];
|
||||
pluginImpls: PluginReturn<TData, TParams>[] = []
|
||||
|
||||
count: number = 0;
|
||||
count: number = 0
|
||||
|
||||
state: FetchState<TData, TParams> = reactive({
|
||||
loading: false,
|
||||
params: undefined,
|
||||
data: undefined,
|
||||
error: undefined,
|
||||
});
|
||||
})
|
||||
|
||||
constructor(
|
||||
public serviceRef: Service<TData, TParams>,
|
||||
@@ -22,126 +22,126 @@ export default class Fetch<TData, TParams extends any[]> {
|
||||
public subscribe: Subscribe,
|
||||
public initState: Partial<FetchState<TData, TParams>> = {},
|
||||
) {
|
||||
this.setState({ loading: !options.manual, ...initState });
|
||||
this.setState({ loading: !options.manual, ...initState })
|
||||
}
|
||||
|
||||
setState(s: Partial<FetchState<TData, TParams>> = {}) {
|
||||
Object.assign(this.state, s);
|
||||
this.subscribe();
|
||||
Object.assign(this.state, s)
|
||||
this.subscribe()
|
||||
}
|
||||
|
||||
runPluginHandler(event: keyof PluginReturn<TData, TParams>, ...rest: any[]) {
|
||||
// @ts-ignore
|
||||
const r = this.pluginImpls.map((i) => i[event]?.(...rest)).filter(Boolean);
|
||||
return Object.assign({}, ...r);
|
||||
const r = this.pluginImpls.map((i) => i[event]?.(...rest)).filter(Boolean)
|
||||
return Object.assign({}, ...r)
|
||||
}
|
||||
|
||||
async runAsync(...params: TParams): Promise<TData> {
|
||||
this.count += 1;
|
||||
const currentCount = this.count;
|
||||
this.count += 1
|
||||
const currentCount = this.count
|
||||
|
||||
const {
|
||||
stopNow = false,
|
||||
returnNow = false,
|
||||
...state
|
||||
} = this.runPluginHandler('onBefore', params);
|
||||
} = this.runPluginHandler('onBefore', params)
|
||||
|
||||
// stop request
|
||||
if (stopNow) {
|
||||
return new Promise(() => {});
|
||||
return new Promise(() => {})
|
||||
}
|
||||
|
||||
this.setState({
|
||||
loading: true,
|
||||
params,
|
||||
...state,
|
||||
});
|
||||
})
|
||||
|
||||
// return now
|
||||
if (returnNow) {
|
||||
return Promise.resolve(state.data);
|
||||
return Promise.resolve(state.data)
|
||||
}
|
||||
|
||||
this.options.onBefore?.(params);
|
||||
this.options.onBefore?.(params)
|
||||
|
||||
try {
|
||||
// replace service
|
||||
let { servicePromise } = this.runPluginHandler('onRequest', this.serviceRef, params);
|
||||
let { servicePromise } = this.runPluginHandler('onRequest', this.serviceRef, params)
|
||||
|
||||
if (!servicePromise) {
|
||||
servicePromise = this.serviceRef(...params);
|
||||
servicePromise = this.serviceRef(...params)
|
||||
}
|
||||
|
||||
const res = await servicePromise;
|
||||
const res = await servicePromise
|
||||
|
||||
if (currentCount !== this.count) {
|
||||
// prevent run.then when request is canceled
|
||||
return new Promise(() => {});
|
||||
return new Promise(() => {})
|
||||
}
|
||||
|
||||
// const formattedResult = this.options.formatResultRef.current ? this.options.formatResultRef.current(res) : res;
|
||||
|
||||
this.setState({ data: res, error: undefined, loading: false });
|
||||
this.setState({ data: res, error: undefined, loading: false })
|
||||
|
||||
this.options.onSuccess?.(res, params);
|
||||
this.runPluginHandler('onSuccess', res, params);
|
||||
this.options.onSuccess?.(res, params)
|
||||
this.runPluginHandler('onSuccess', res, params)
|
||||
|
||||
this.options.onFinally?.(params, res, undefined);
|
||||
this.options.onFinally?.(params, res, undefined)
|
||||
|
||||
if (currentCount === this.count) {
|
||||
this.runPluginHandler('onFinally', params, res, undefined);
|
||||
this.runPluginHandler('onFinally', params, res, undefined)
|
||||
}
|
||||
|
||||
return res;
|
||||
return res
|
||||
} catch (error) {
|
||||
if (currentCount !== this.count) {
|
||||
// prevent run.then when request is canceled
|
||||
return new Promise(() => {});
|
||||
return new Promise(() => {})
|
||||
}
|
||||
|
||||
this.setState({ error, loading: false });
|
||||
this.setState({ error, loading: false })
|
||||
|
||||
this.options.onError?.(error, params);
|
||||
this.runPluginHandler('onError', error, params);
|
||||
this.options.onError?.(error, params)
|
||||
this.runPluginHandler('onError', error, params)
|
||||
|
||||
this.options.onFinally?.(params, undefined, error);
|
||||
this.options.onFinally?.(params, undefined, error)
|
||||
|
||||
if (currentCount === this.count) {
|
||||
this.runPluginHandler('onFinally', params, undefined, error);
|
||||
this.runPluginHandler('onFinally', params, undefined, error)
|
||||
}
|
||||
|
||||
throw error;
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
run(...params: TParams) {
|
||||
this.runAsync(...params).catch((error) => {
|
||||
if (!this.options.onError) {
|
||||
console.error(error);
|
||||
console.error(error)
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.count += 1;
|
||||
this.setState({ loading: false });
|
||||
this.count += 1
|
||||
this.setState({ loading: false })
|
||||
|
||||
this.runPluginHandler('onCancel');
|
||||
this.runPluginHandler('onCancel')
|
||||
}
|
||||
|
||||
refresh() {
|
||||
// @ts-ignore
|
||||
this.run(...(this.state.params || []));
|
||||
this.run(...(this.state.params || []))
|
||||
}
|
||||
|
||||
refreshAsync() {
|
||||
// @ts-ignore
|
||||
return this.runAsync(...(this.state.params || []));
|
||||
return this.runAsync(...(this.state.params || []))
|
||||
}
|
||||
|
||||
mutate(data?: TData | ((oldData?: TData) => TData | undefined)) {
|
||||
const targetData = isFunction(data) ? data(this.state.data) : data;
|
||||
this.runPluginHandler('onMutate', targetData);
|
||||
this.setState({ data: targetData });
|
||||
const targetData = isFunction(data) ? data(this.state.data) : data
|
||||
this.runPluginHandler('onMutate', targetData)
|
||||
this.setState({ data: targetData })
|
||||
}
|
||||
}
|
||||
|
@@ -1,15 +1,15 @@
|
||||
import useAutoRunPlugin from './plugins/useAutoRunPlugin';
|
||||
import useCachePlugin from './plugins/useCachePlugin';
|
||||
import useDebouncePlugin from './plugins/useDebouncePlugin';
|
||||
import useLoadingDelayPlugin from './plugins/useLoadingDelayPlugin';
|
||||
import usePollingPlugin from './plugins/usePollingPlugin';
|
||||
import useRefreshOnWindowFocusPlugin from './plugins/useRefreshOnWindowFocusPlugin';
|
||||
import useRetryPlugin from './plugins/useRetryPlugin';
|
||||
import useThrottlePlugin from './plugins/useThrottlePlugin';
|
||||
import type { Service, UseRequestOptions, UseRequestPlugin } from './types';
|
||||
import { useRequestImplement } from './useRequestImplement';
|
||||
import useAutoRunPlugin from './plugins/useAutoRunPlugin'
|
||||
import useCachePlugin from './plugins/useCachePlugin'
|
||||
import useDebouncePlugin from './plugins/useDebouncePlugin'
|
||||
import useLoadingDelayPlugin from './plugins/useLoadingDelayPlugin'
|
||||
import usePollingPlugin from './plugins/usePollingPlugin'
|
||||
import useRefreshOnWindowFocusPlugin from './plugins/useRefreshOnWindowFocusPlugin'
|
||||
import useRetryPlugin from './plugins/useRetryPlugin'
|
||||
import useThrottlePlugin from './plugins/useThrottlePlugin'
|
||||
import type { Service, UseRequestOptions, UseRequestPlugin } from './types'
|
||||
import { useRequestImplement } from './useRequestImplement'
|
||||
|
||||
export { clearCache } from './utils/cache';
|
||||
export { clearCache } from './utils/cache'
|
||||
|
||||
export function useRequest<TData, TParams extends any[]>(
|
||||
service: Service<TData, TParams>,
|
||||
@@ -26,5 +26,5 @@ export function useRequest<TData, TParams extends any[]>(
|
||||
useAutoRunPlugin,
|
||||
useCachePlugin,
|
||||
useRetryPlugin,
|
||||
] as UseRequestPlugin<TData, TParams>[]);
|
||||
] as UseRequestPlugin<TData, TParams>[])
|
||||
}
|
||||
|
@@ -1,52 +1,52 @@
|
||||
import { ref, unref, watch } from 'vue';
|
||||
import { ref, unref, watch } from 'vue'
|
||||
|
||||
import type { UseRequestPlugin } from '../types';
|
||||
import type { UseRequestPlugin } from '../types'
|
||||
|
||||
// support refreshDeps & ready
|
||||
const useAutoRunPlugin: UseRequestPlugin<any, any[]> = (
|
||||
fetchInstance,
|
||||
{ manual, ready = true, defaultParams = [], refreshDeps = [], refreshDepsAction },
|
||||
) => {
|
||||
const hasAutoRun = ref(false);
|
||||
const hasAutoRun = ref(false)
|
||||
|
||||
watch(
|
||||
() => unref(ready),
|
||||
(readyVal) => {
|
||||
if (!unref(manual) && readyVal) {
|
||||
hasAutoRun.value = true;
|
||||
fetchInstance.run(...defaultParams);
|
||||
hasAutoRun.value = true
|
||||
fetchInstance.run(...defaultParams)
|
||||
}
|
||||
},
|
||||
);
|
||||
)
|
||||
|
||||
if (refreshDeps.length) {
|
||||
watch(refreshDeps, () => {
|
||||
if (hasAutoRun.value) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
if (!manual) {
|
||||
if (refreshDepsAction) {
|
||||
refreshDepsAction();
|
||||
refreshDepsAction()
|
||||
} else {
|
||||
fetchInstance.refresh();
|
||||
fetchInstance.refresh()
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
onBefore: () => {
|
||||
if (!unref(ready)) {
|
||||
return { stopNow: true };
|
||||
return { stopNow: true }
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
useAutoRunPlugin.onInit = ({ ready = true, manual }) => {
|
||||
return {
|
||||
loading: !unref(manual) && unref(ready),
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default useAutoRunPlugin;
|
||||
export default useAutoRunPlugin
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import { onUnmounted, ref, watchEffect } from 'vue';
|
||||
import { onUnmounted, ref, watchEffect } from 'vue'
|
||||
|
||||
import type { UseRequestPlugin } from '../types';
|
||||
import type { CachedData } from '../utils/cache';
|
||||
import { getCache, setCache } from '../utils/cache';
|
||||
import { getCachePromise, setCachePromise } from '../utils/cachePromise';
|
||||
import { subscribe, trigger } from '../utils/cacheSubscribe';
|
||||
import type { UseRequestPlugin } from '../types'
|
||||
import type { CachedData } from '../utils/cache'
|
||||
import { getCache, setCache } from '../utils/cache'
|
||||
import { getCachePromise, setCachePromise } from '../utils/cachePromise'
|
||||
import { subscribe, trigger } from '../utils/cacheSubscribe'
|
||||
|
||||
const useCachePlugin: UseRequestPlugin<any, any[]> = (
|
||||
fetchInstance,
|
||||
@@ -16,52 +16,52 @@ const useCachePlugin: UseRequestPlugin<any, any[]> = (
|
||||
getCache: customGetCache,
|
||||
},
|
||||
) => {
|
||||
const unSubscribeRef = ref<() => void>();
|
||||
const currentPromiseRef = ref<Promise<any>>();
|
||||
const unSubscribeRef = ref<() => void>()
|
||||
const currentPromiseRef = ref<Promise<any>>()
|
||||
|
||||
const _setCache = (key: string, cachedData: CachedData) => {
|
||||
customSetCache ? customSetCache(cachedData) : setCache(key, cacheTime, cachedData);
|
||||
trigger(key, cachedData.data);
|
||||
};
|
||||
customSetCache ? customSetCache(cachedData) : setCache(key, cacheTime, cachedData)
|
||||
trigger(key, cachedData.data)
|
||||
}
|
||||
|
||||
const _getCache = (key: string, params: any[] = []) => {
|
||||
return customGetCache ? customGetCache(params) : getCache(key);
|
||||
};
|
||||
return customGetCache ? customGetCache(params) : getCache(key)
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
if (!cacheKey) return;
|
||||
if (!cacheKey) return
|
||||
|
||||
// get data from cache when init
|
||||
const cacheData = _getCache(cacheKey);
|
||||
const cacheData = _getCache(cacheKey)
|
||||
if (cacheData && Object.hasOwnProperty.call(cacheData, 'data')) {
|
||||
fetchInstance.state.data = cacheData.data;
|
||||
fetchInstance.state.params = cacheData.params;
|
||||
fetchInstance.state.data = cacheData.data
|
||||
fetchInstance.state.params = cacheData.params
|
||||
|
||||
if (staleTime === -1 || new Date().getTime() - cacheData.time <= staleTime) {
|
||||
fetchInstance.state.loading = false;
|
||||
fetchInstance.state.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
// subscribe same cachekey update, trigger update
|
||||
unSubscribeRef.value = subscribe(cacheKey, (data) => {
|
||||
fetchInstance.setState({ data });
|
||||
});
|
||||
});
|
||||
fetchInstance.setState({ data })
|
||||
})
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
unSubscribeRef.value?.();
|
||||
});
|
||||
unSubscribeRef.value?.()
|
||||
})
|
||||
|
||||
if (!cacheKey) {
|
||||
return {};
|
||||
return {}
|
||||
}
|
||||
|
||||
return {
|
||||
onBefore: (params) => {
|
||||
const cacheData = _getCache(cacheKey, params);
|
||||
const cacheData = _getCache(cacheKey, params)
|
||||
|
||||
if (!cacheData || !Object.hasOwnProperty.call(cacheData, 'data')) {
|
||||
return {};
|
||||
return {}
|
||||
}
|
||||
|
||||
// If the data is fresh, stop request
|
||||
@@ -71,57 +71,57 @@ const useCachePlugin: UseRequestPlugin<any, any[]> = (
|
||||
data: cacheData?.data,
|
||||
error: undefined,
|
||||
returnNow: true,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// If the data is stale, return data, and request continue
|
||||
return { data: cacheData?.data, error: undefined };
|
||||
return { data: cacheData?.data, error: undefined }
|
||||
}
|
||||
},
|
||||
onRequest: (service, args) => {
|
||||
let servicePromise = getCachePromise(cacheKey);
|
||||
let servicePromise = getCachePromise(cacheKey)
|
||||
|
||||
// If has servicePromise, and is not trigger by self, then use it
|
||||
if (servicePromise && servicePromise !== currentPromiseRef.value) {
|
||||
return { servicePromise };
|
||||
return { servicePromise }
|
||||
}
|
||||
|
||||
servicePromise = service(...args);
|
||||
currentPromiseRef.value = servicePromise;
|
||||
setCachePromise(cacheKey, servicePromise);
|
||||
servicePromise = service(...args)
|
||||
currentPromiseRef.value = servicePromise
|
||||
setCachePromise(cacheKey, servicePromise)
|
||||
|
||||
return { servicePromise };
|
||||
return { servicePromise }
|
||||
},
|
||||
onSuccess: (data, params) => {
|
||||
if (cacheKey) {
|
||||
// cancel subscribe, avoid trgger self
|
||||
unSubscribeRef.value?.();
|
||||
unSubscribeRef.value?.()
|
||||
|
||||
_setCache(cacheKey, { data, params, time: new Date().getTime() });
|
||||
_setCache(cacheKey, { data, params, time: new Date().getTime() })
|
||||
|
||||
// resubscribe
|
||||
unSubscribeRef.value = subscribe(cacheKey, (d) => {
|
||||
fetchInstance.setState({ data: d });
|
||||
});
|
||||
fetchInstance.setState({ data: d })
|
||||
})
|
||||
}
|
||||
},
|
||||
onMutate: (data) => {
|
||||
if (cacheKey) {
|
||||
// cancel subscribe, avoid trigger self
|
||||
unSubscribeRef.value?.();
|
||||
unSubscribeRef.value?.()
|
||||
|
||||
_setCache(cacheKey, {
|
||||
data,
|
||||
params: fetchInstance.state.params,
|
||||
time: new Date().getTime(),
|
||||
});
|
||||
})
|
||||
|
||||
// resubscribe
|
||||
unSubscribeRef.value = subscribe(cacheKey, (d) => {
|
||||
fetchInstance.setState({ data: d });
|
||||
});
|
||||
fetchInstance.setState({ data: d })
|
||||
})
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default useCachePlugin;
|
||||
export default useCachePlugin
|
||||
|
@@ -1,42 +1,42 @@
|
||||
import type { DebouncedFunc, DebounceSettings } from 'lodash-es';
|
||||
import { debounce } from 'lodash-es';
|
||||
import { computed, ref, watchEffect } from 'vue';
|
||||
import type { DebouncedFunc, DebounceSettings } from 'lodash-es'
|
||||
import { debounce } from 'lodash-es'
|
||||
import { computed, ref, watchEffect } from 'vue'
|
||||
|
||||
import type { UseRequestPlugin } from '../types';
|
||||
import type { UseRequestPlugin } from '../types'
|
||||
|
||||
const useDebouncePlugin: UseRequestPlugin<any, any[]> = (
|
||||
fetchInstance,
|
||||
{ debounceWait, debounceLeading, debounceTrailing, debounceMaxWait },
|
||||
) => {
|
||||
const debouncedRef = ref<DebouncedFunc<any>>();
|
||||
const debouncedRef = ref<DebouncedFunc<any>>()
|
||||
|
||||
const options = computed(() => {
|
||||
const ret: DebounceSettings = {};
|
||||
const ret: DebounceSettings = {}
|
||||
|
||||
if (debounceLeading !== undefined) {
|
||||
ret.leading = debounceLeading;
|
||||
ret.leading = debounceLeading
|
||||
}
|
||||
if (debounceTrailing !== undefined) {
|
||||
ret.trailing = debounceTrailing;
|
||||
ret.trailing = debounceTrailing
|
||||
}
|
||||
if (debounceMaxWait !== undefined) {
|
||||
ret.maxWait = debounceMaxWait;
|
||||
ret.maxWait = debounceMaxWait
|
||||
}
|
||||
|
||||
return ret;
|
||||
});
|
||||
return ret
|
||||
})
|
||||
|
||||
watchEffect(() => {
|
||||
if (debounceWait) {
|
||||
const _originRunAsync = fetchInstance.runAsync.bind(fetchInstance);
|
||||
const _originRunAsync = fetchInstance.runAsync.bind(fetchInstance)
|
||||
|
||||
debouncedRef.value = debounce(
|
||||
(callback) => {
|
||||
callback();
|
||||
callback()
|
||||
},
|
||||
debounceWait,
|
||||
options.value,
|
||||
);
|
||||
)
|
||||
|
||||
// debounce runAsync should be promise
|
||||
// https://github.com/lodash/lodash/issues/4400#issuecomment-834800398
|
||||
@@ -45,27 +45,27 @@ const useDebouncePlugin: UseRequestPlugin<any, any[]> = (
|
||||
debouncedRef.value?.(() => {
|
||||
_originRunAsync(...args)
|
||||
.then(resolve)
|
||||
.catch(reject);
|
||||
});
|
||||
});
|
||||
};
|
||||
.catch(reject)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return () => {
|
||||
debouncedRef.value?.cancel();
|
||||
fetchInstance.runAsync = _originRunAsync;
|
||||
};
|
||||
debouncedRef.value?.cancel()
|
||||
fetchInstance.runAsync = _originRunAsync
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
if (!debounceWait) {
|
||||
return {};
|
||||
return {}
|
||||
}
|
||||
|
||||
return {
|
||||
onCancel: () => {
|
||||
debouncedRef.value?.cancel();
|
||||
debouncedRef.value?.cancel()
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default useDebouncePlugin;
|
||||
export default useDebouncePlugin
|
||||
|
@@ -1,45 +1,45 @@
|
||||
import { ref, unref } from 'vue';
|
||||
import { ref, unref } from 'vue'
|
||||
|
||||
import type { UseRequestPlugin, UseRequestTimeout } from '../types';
|
||||
import type { UseRequestPlugin, UseRequestTimeout } from '../types'
|
||||
|
||||
const useLoadingDelayPlugin: UseRequestPlugin<any, any[]> = (
|
||||
fetchInstance,
|
||||
{ loadingDelay, ready },
|
||||
) => {
|
||||
const timerRef = ref<UseRequestTimeout>();
|
||||
const timerRef = ref<UseRequestTimeout>()
|
||||
|
||||
if (!loadingDelay) {
|
||||
return {};
|
||||
return {}
|
||||
}
|
||||
|
||||
const cancelTimeout = () => {
|
||||
if (timerRef.value) {
|
||||
clearTimeout(timerRef.value);
|
||||
clearTimeout(timerRef.value)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
onBefore: () => {
|
||||
cancelTimeout();
|
||||
cancelTimeout()
|
||||
|
||||
// Two cases:
|
||||
// 1. ready === undefined
|
||||
// 2. ready === true
|
||||
if (unref(ready) !== false) {
|
||||
timerRef.value = setTimeout(() => {
|
||||
fetchInstance.setState({ loading: true });
|
||||
}, loadingDelay);
|
||||
fetchInstance.setState({ loading: true })
|
||||
}, loadingDelay)
|
||||
}
|
||||
|
||||
return { loading: false };
|
||||
return { loading: false }
|
||||
},
|
||||
onFinally: () => {
|
||||
cancelTimeout();
|
||||
cancelTimeout()
|
||||
},
|
||||
onCancel: () => {
|
||||
cancelTimeout();
|
||||
cancelTimeout()
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default useLoadingDelayPlugin;
|
||||
export default useLoadingDelayPlugin
|
||||
|
@@ -1,46 +1,46 @@
|
||||
import { ref, watch } from 'vue';
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
import type { UseRequestPlugin, UseRequestTimeout } from '../types';
|
||||
import { isDocumentVisible } from '../utils/isDocumentVisible';
|
||||
import subscribeReVisible from '../utils/subscribeReVisible';
|
||||
import type { UseRequestPlugin, UseRequestTimeout } from '../types'
|
||||
import { isDocumentVisible } from '../utils/isDocumentVisible'
|
||||
import subscribeReVisible from '../utils/subscribeReVisible'
|
||||
|
||||
const usePollingPlugin: UseRequestPlugin<any, any[]> = (
|
||||
fetchInstance,
|
||||
{ pollingInterval, pollingWhenHidden = true, pollingErrorRetryCount = -1 },
|
||||
) => {
|
||||
const timerRef = ref<UseRequestTimeout>();
|
||||
const unsubscribeRef = ref<() => void>();
|
||||
const countRef = ref<number>(0);
|
||||
const timerRef = ref<UseRequestTimeout>()
|
||||
const unsubscribeRef = ref<() => void>()
|
||||
const countRef = ref<number>(0)
|
||||
|
||||
const stopPolling = () => {
|
||||
if (timerRef.value) {
|
||||
clearTimeout(timerRef.value);
|
||||
clearTimeout(timerRef.value)
|
||||
}
|
||||
unsubscribeRef.value?.();
|
||||
};
|
||||
unsubscribeRef.value?.()
|
||||
}
|
||||
|
||||
watch(
|
||||
() => pollingInterval,
|
||||
() => {
|
||||
if (!pollingInterval) {
|
||||
stopPolling();
|
||||
stopPolling()
|
||||
}
|
||||
},
|
||||
);
|
||||
)
|
||||
|
||||
if (!pollingInterval) {
|
||||
return {};
|
||||
return {}
|
||||
}
|
||||
|
||||
return {
|
||||
onBefore: () => {
|
||||
stopPolling();
|
||||
stopPolling()
|
||||
},
|
||||
onError: () => {
|
||||
countRef.value += 1;
|
||||
countRef.value += 1
|
||||
},
|
||||
onSuccess: () => {
|
||||
countRef.value = 0;
|
||||
countRef.value = 0
|
||||
},
|
||||
onFinally: () => {
|
||||
if (
|
||||
@@ -52,20 +52,20 @@ const usePollingPlugin: UseRequestPlugin<any, any[]> = (
|
||||
// if pollingWhenHidden = false && document is hidden, then stop polling and subscribe revisible
|
||||
if (!pollingWhenHidden && !isDocumentVisible()) {
|
||||
unsubscribeRef.value = subscribeReVisible(() => {
|
||||
fetchInstance.refresh();
|
||||
});
|
||||
fetchInstance.refresh()
|
||||
})
|
||||
} else {
|
||||
fetchInstance.refresh();
|
||||
fetchInstance.refresh()
|
||||
}
|
||||
}, pollingInterval);
|
||||
}, pollingInterval)
|
||||
} else {
|
||||
countRef.value = 0;
|
||||
countRef.value = 0
|
||||
}
|
||||
},
|
||||
onCancel: () => {
|
||||
stopPolling();
|
||||
stopPolling()
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default usePollingPlugin;
|
||||
export default usePollingPlugin
|
||||
|
@@ -1,37 +1,37 @@
|
||||
import { onUnmounted, ref, watchEffect } from 'vue';
|
||||
import { onUnmounted, ref, watchEffect } from 'vue'
|
||||
|
||||
import type { UseRequestPlugin } from '../types';
|
||||
import { limit } from '../utils/limit';
|
||||
import subscribeFocus from '../utils/subscribeFocus';
|
||||
import type { UseRequestPlugin } from '../types'
|
||||
import { limit } from '../utils/limit'
|
||||
import subscribeFocus from '../utils/subscribeFocus'
|
||||
|
||||
const useRefreshOnWindowFocusPlugin: UseRequestPlugin<any, any[]> = (
|
||||
fetchInstance,
|
||||
{ refreshOnWindowFocus, focusTimespan = 5000 },
|
||||
) => {
|
||||
const unsubscribeRef = ref<() => void>();
|
||||
const unsubscribeRef = ref<() => void>()
|
||||
|
||||
const stopSubscribe = () => {
|
||||
unsubscribeRef.value?.();
|
||||
};
|
||||
unsubscribeRef.value?.()
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
if (refreshOnWindowFocus) {
|
||||
const limitRefresh = limit(fetchInstance.refresh.bind(fetchInstance), focusTimespan);
|
||||
const limitRefresh = limit(fetchInstance.refresh.bind(fetchInstance), focusTimespan)
|
||||
unsubscribeRef.value = subscribeFocus(() => {
|
||||
limitRefresh();
|
||||
});
|
||||
limitRefresh()
|
||||
})
|
||||
}
|
||||
|
||||
return () => {
|
||||
stopSubscribe();
|
||||
};
|
||||
});
|
||||
stopSubscribe()
|
||||
}
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
stopSubscribe();
|
||||
});
|
||||
stopSubscribe()
|
||||
})
|
||||
|
||||
return {};
|
||||
};
|
||||
return {}
|
||||
}
|
||||
|
||||
export default useRefreshOnWindowFocusPlugin;
|
||||
export default useRefreshOnWindowFocusPlugin
|
||||
|
@@ -1,54 +1,54 @@
|
||||
import { ref } from 'vue';
|
||||
import { ref } from 'vue'
|
||||
|
||||
import type { UseRequestPlugin, UseRequestTimeout } from '../types';
|
||||
import type { UseRequestPlugin, UseRequestTimeout } from '../types'
|
||||
|
||||
const useRetryPlugin: UseRequestPlugin<any, any[]> = (
|
||||
fetchInstance,
|
||||
{ retryInterval, retryCount },
|
||||
) => {
|
||||
const timerRef = ref<UseRequestTimeout>();
|
||||
const countRef = ref(0);
|
||||
const timerRef = ref<UseRequestTimeout>()
|
||||
const countRef = ref(0)
|
||||
|
||||
const triggerByRetry = ref(false);
|
||||
const triggerByRetry = ref(false)
|
||||
|
||||
if (!retryCount) {
|
||||
return {};
|
||||
return {}
|
||||
}
|
||||
|
||||
return {
|
||||
onBefore: () => {
|
||||
if (!triggerByRetry.value) {
|
||||
countRef.value = 0;
|
||||
countRef.value = 0
|
||||
}
|
||||
triggerByRetry.value = false;
|
||||
triggerByRetry.value = false
|
||||
|
||||
if (timerRef.value) {
|
||||
clearTimeout(timerRef.value);
|
||||
clearTimeout(timerRef.value)
|
||||
}
|
||||
},
|
||||
onSuccess: () => {
|
||||
countRef.value = 0;
|
||||
countRef.value = 0
|
||||
},
|
||||
onError: () => {
|
||||
countRef.value += 1;
|
||||
countRef.value += 1
|
||||
if (retryCount === -1 || countRef.value <= retryCount) {
|
||||
// Exponential backoff
|
||||
const timeout = retryInterval ?? Math.min(1000 * 2 ** countRef.value, 30000);
|
||||
const timeout = retryInterval ?? Math.min(1000 * 2 ** countRef.value, 30000)
|
||||
timerRef.value = setTimeout(() => {
|
||||
triggerByRetry.value = true;
|
||||
fetchInstance.refresh();
|
||||
}, timeout);
|
||||
triggerByRetry.value = true
|
||||
fetchInstance.refresh()
|
||||
}, timeout)
|
||||
} else {
|
||||
countRef.value = 0;
|
||||
countRef.value = 0
|
||||
}
|
||||
},
|
||||
onCancel: () => {
|
||||
countRef.value = 0;
|
||||
countRef.value = 0
|
||||
if (timerRef.value) {
|
||||
clearTimeout(timerRef.value);
|
||||
clearTimeout(timerRef.value)
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default useRetryPlugin;
|
||||
export default useRetryPlugin
|
||||
|
@@ -1,34 +1,34 @@
|
||||
import type { DebouncedFunc, ThrottleSettings } from 'lodash-es';
|
||||
import { throttle } from 'lodash-es';
|
||||
import { ref, watchEffect } from 'vue';
|
||||
import type { DebouncedFunc, ThrottleSettings } from 'lodash-es'
|
||||
import { throttle } from 'lodash-es'
|
||||
import { ref, watchEffect } from 'vue'
|
||||
|
||||
import type { UseRequestPlugin } from '../types';
|
||||
import type { UseRequestPlugin } from '../types'
|
||||
|
||||
const useThrottlePlugin: UseRequestPlugin<any, any[]> = (
|
||||
fetchInstance,
|
||||
{ throttleWait, throttleLeading, throttleTrailing },
|
||||
) => {
|
||||
const throttledRef = ref<DebouncedFunc<any>>();
|
||||
const throttledRef = ref<DebouncedFunc<any>>()
|
||||
|
||||
const options: ThrottleSettings = {};
|
||||
const options: ThrottleSettings = {}
|
||||
if (throttleLeading !== undefined) {
|
||||
options.leading = throttleLeading;
|
||||
options.leading = throttleLeading
|
||||
}
|
||||
if (throttleTrailing !== undefined) {
|
||||
options.trailing = throttleTrailing;
|
||||
options.trailing = throttleTrailing
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
if (throttleWait) {
|
||||
const _originRunAsync = fetchInstance.runAsync.bind(fetchInstance);
|
||||
const _originRunAsync = fetchInstance.runAsync.bind(fetchInstance)
|
||||
|
||||
throttledRef.value = throttle(
|
||||
(callback) => {
|
||||
callback();
|
||||
callback()
|
||||
},
|
||||
throttleWait,
|
||||
options,
|
||||
);
|
||||
)
|
||||
|
||||
// throttle runAsync should be promise
|
||||
// https://github.com/lodash/lodash/issues/4400#issuecomment-834800398
|
||||
@@ -37,27 +37,27 @@ const useThrottlePlugin: UseRequestPlugin<any, any[]> = (
|
||||
throttledRef.value?.(() => {
|
||||
_originRunAsync(...args)
|
||||
.then(resolve)
|
||||
.catch(reject);
|
||||
});
|
||||
});
|
||||
};
|
||||
.catch(reject)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return () => {
|
||||
fetchInstance.runAsync = _originRunAsync;
|
||||
throttledRef.value?.cancel();
|
||||
};
|
||||
fetchInstance.runAsync = _originRunAsync
|
||||
throttledRef.value?.cancel()
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
if (!throttleWait) {
|
||||
return {};
|
||||
return {}
|
||||
}
|
||||
|
||||
return {
|
||||
onCancel: () => {
|
||||
throttledRef.value?.cancel();
|
||||
throttledRef.value?.cancel()
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default useThrottlePlugin;
|
||||
export default useThrottlePlugin
|
||||
|
@@ -1,93 +1,93 @@
|
||||
import type { MaybeRef, Ref, WatchSource } from 'vue';
|
||||
import type { MaybeRef, Ref, WatchSource } from 'vue'
|
||||
|
||||
import type Fetch from './Fetch';
|
||||
import type { CachedData } from './utils/cache';
|
||||
import type Fetch from './Fetch'
|
||||
import type { CachedData } from './utils/cache'
|
||||
|
||||
export type Service<TData, TParams extends any[]> = (...args: TParams) => Promise<TData>;
|
||||
export type Subscribe = () => void;
|
||||
export type Service<TData, TParams extends any[]> = (...args: TParams) => Promise<TData>
|
||||
export type Subscribe = () => void
|
||||
|
||||
// for Fetch
|
||||
export interface FetchState<TData, TParams extends any[]> {
|
||||
loading: boolean;
|
||||
params?: TParams;
|
||||
data?: TData;
|
||||
error?: Error;
|
||||
loading: boolean
|
||||
params?: TParams
|
||||
data?: TData
|
||||
error?: Error
|
||||
}
|
||||
|
||||
export interface PluginReturn<TData, TParams extends any[]> {
|
||||
onBefore?: (params: TParams) =>
|
||||
| ({
|
||||
stopNow?: boolean;
|
||||
returnNow?: boolean;
|
||||
stopNow?: boolean
|
||||
returnNow?: boolean
|
||||
} & Partial<FetchState<TData, TParams>>)
|
||||
| void;
|
||||
| void
|
||||
|
||||
onRequest?: (
|
||||
service: Service<TData, TParams>,
|
||||
params: TParams,
|
||||
) => {
|
||||
servicePromise?: Promise<TData>;
|
||||
};
|
||||
servicePromise?: Promise<TData>
|
||||
}
|
||||
|
||||
onSuccess?: (data: TData, params: TParams) => void;
|
||||
onError?: (e: Error, params: TParams) => void;
|
||||
onFinally?: (params: TParams, data?: TData, e?: Error) => void;
|
||||
onCancel?: () => void;
|
||||
onMutate?: (data: TData) => void;
|
||||
onSuccess?: (data: TData, params: TParams) => void
|
||||
onError?: (e: Error, params: TParams) => void
|
||||
onFinally?: (params: TParams, data?: TData, e?: Error) => void
|
||||
onCancel?: () => void
|
||||
onMutate?: (data: TData) => void
|
||||
}
|
||||
|
||||
// for useRequestImplement
|
||||
export interface UseRequestOptions<TData, TParams extends any[]> {
|
||||
manual?: MaybeRef<boolean>;
|
||||
manual?: MaybeRef<boolean>
|
||||
|
||||
onBefore?: (params: TParams) => void;
|
||||
onSuccess?: (data: TData, params: TParams) => void;
|
||||
onError?: (e: Error, params: TParams) => void;
|
||||
onBefore?: (params: TParams) => void
|
||||
onSuccess?: (data: TData, params: TParams) => void
|
||||
onError?: (e: Error, params: TParams) => void
|
||||
// formatResult?: (res: any) => TData;
|
||||
onFinally?: (params: TParams, data?: TData, e?: Error) => void;
|
||||
onFinally?: (params: TParams, data?: TData, e?: Error) => void
|
||||
|
||||
defaultParams?: TParams;
|
||||
defaultParams?: TParams
|
||||
|
||||
// refreshDeps
|
||||
refreshDeps?: WatchSource<any>[];
|
||||
refreshDepsAction?: () => void;
|
||||
refreshDeps?: WatchSource<any>[]
|
||||
refreshDepsAction?: () => void
|
||||
|
||||
// loading delay
|
||||
loadingDelay?: number;
|
||||
loadingDelay?: number
|
||||
|
||||
// polling
|
||||
pollingInterval?: number;
|
||||
pollingWhenHidden?: boolean;
|
||||
pollingErrorRetryCount?: number;
|
||||
pollingInterval?: number
|
||||
pollingWhenHidden?: boolean
|
||||
pollingErrorRetryCount?: number
|
||||
|
||||
// refresh on window focus
|
||||
refreshOnWindowFocus?: boolean;
|
||||
focusTimespan?: number;
|
||||
refreshOnWindowFocus?: boolean
|
||||
focusTimespan?: number
|
||||
|
||||
// debounce
|
||||
debounceWait?: number;
|
||||
debounceLeading?: boolean;
|
||||
debounceTrailing?: boolean;
|
||||
debounceMaxWait?: number;
|
||||
debounceWait?: number
|
||||
debounceLeading?: boolean
|
||||
debounceTrailing?: boolean
|
||||
debounceMaxWait?: number
|
||||
|
||||
// throttle
|
||||
throttleWait?: number;
|
||||
throttleLeading?: boolean;
|
||||
throttleTrailing?: boolean;
|
||||
throttleWait?: number
|
||||
throttleLeading?: boolean
|
||||
throttleTrailing?: boolean
|
||||
|
||||
// cache
|
||||
cacheKey?: string;
|
||||
cacheTime?: number;
|
||||
staleTime?: number;
|
||||
setCache?: (data: CachedData<TData, TParams>) => void;
|
||||
getCache?: (params: TParams) => CachedData<TData, TParams> | undefined;
|
||||
cacheKey?: string
|
||||
cacheTime?: number
|
||||
staleTime?: number
|
||||
setCache?: (data: CachedData<TData, TParams>) => void
|
||||
getCache?: (params: TParams) => CachedData<TData, TParams> | undefined
|
||||
|
||||
// retry
|
||||
retryCount?: number;
|
||||
retryInterval?: number;
|
||||
retryCount?: number
|
||||
retryInterval?: number
|
||||
|
||||
// ready
|
||||
ready?: MaybeRef<boolean>;
|
||||
ready?: MaybeRef<boolean>
|
||||
|
||||
// [key: string]: any;
|
||||
}
|
||||
@@ -97,8 +97,8 @@ export interface UseRequestPlugin<TData, TParams extends any[]> {
|
||||
(
|
||||
fetchInstance: Fetch<TData, TParams>,
|
||||
options: UseRequestOptions<TData, TParams>,
|
||||
): PluginReturn<TData, TParams>;
|
||||
onInit?: (options: UseRequestOptions<TData, TParams>) => Partial<FetchState<TData, TParams>>;
|
||||
): PluginReturn<TData, TParams>
|
||||
onInit?: (options: UseRequestOptions<TData, TParams>) => Partial<FetchState<TData, TParams>>
|
||||
}
|
||||
|
||||
// for index
|
||||
@@ -109,16 +109,16 @@ export interface UseRequestPlugin<TData, TParams extends any[]> {
|
||||
// };
|
||||
|
||||
export interface UseRequestResult<TData, TParams extends any[]> {
|
||||
loading: Ref<boolean>;
|
||||
data: Ref<TData>;
|
||||
error: Ref<Error>;
|
||||
params: Ref<TParams | []>;
|
||||
cancel: Fetch<TData, TParams>['cancel'];
|
||||
refresh: Fetch<TData, TParams>['refresh'];
|
||||
refreshAsync: Fetch<TData, TParams>['refreshAsync'];
|
||||
run: Fetch<TData, TParams>['run'];
|
||||
runAsync: Fetch<TData, TParams>['runAsync'];
|
||||
mutate: Fetch<TData, TParams>['mutate'];
|
||||
loading: Ref<boolean>
|
||||
data: Ref<TData>
|
||||
error: Ref<Error>
|
||||
params: Ref<TParams | []>
|
||||
cancel: Fetch<TData, TParams>['cancel']
|
||||
refresh: Fetch<TData, TParams>['refresh']
|
||||
refreshAsync: Fetch<TData, TParams>['refreshAsync']
|
||||
run: Fetch<TData, TParams>['run']
|
||||
runAsync: Fetch<TData, TParams>['runAsync']
|
||||
mutate: Fetch<TData, TParams>['mutate']
|
||||
}
|
||||
|
||||
export type UseRequestTimeout = ReturnType<typeof setTimeout>;
|
||||
export type UseRequestTimeout = ReturnType<typeof setTimeout>
|
||||
|
@@ -1,41 +1,41 @@
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
import { onMounted, onUnmounted, toRefs } from 'vue';
|
||||
import { onMounted, onUnmounted, toRefs } from 'vue'
|
||||
|
||||
import Fetch from './Fetch';
|
||||
import type { Service, UseRequestOptions, UseRequestPlugin, UseRequestResult } from './types';
|
||||
import Fetch from './Fetch'
|
||||
import type { Service, UseRequestOptions, UseRequestPlugin, UseRequestResult } from './types'
|
||||
|
||||
export function useRequestImplement<TData, TParams extends any[]>(
|
||||
service: Service<TData, TParams>,
|
||||
options: UseRequestOptions<TData, TParams> = {},
|
||||
plugins: UseRequestPlugin<TData, TParams>[] = [],
|
||||
) {
|
||||
const { manual = false, ...rest } = options;
|
||||
const fetchOptions = { manual, ...rest };
|
||||
const { manual = false, ...rest } = options
|
||||
const fetchOptions = { manual, ...rest }
|
||||
|
||||
const initState = plugins.map((p) => p?.onInit?.(fetchOptions)).filter(Boolean);
|
||||
const initState = plugins.map((p) => p?.onInit?.(fetchOptions)).filter(Boolean)
|
||||
|
||||
const fetchInstance = new Fetch<TData, TParams>(
|
||||
service,
|
||||
fetchOptions,
|
||||
() => {},
|
||||
Object.assign({}, ...initState),
|
||||
);
|
||||
)
|
||||
|
||||
fetchInstance.options = fetchOptions;
|
||||
fetchInstance.options = fetchOptions
|
||||
// run all plugins hooks
|
||||
fetchInstance.pluginImpls = plugins.map((p) => p(fetchInstance, fetchOptions));
|
||||
fetchInstance.pluginImpls = plugins.map((p) => p(fetchInstance, fetchOptions))
|
||||
|
||||
onMounted(() => {
|
||||
if (!manual) {
|
||||
const params = fetchInstance.state.params || options.defaultParams || [];
|
||||
const params = fetchInstance.state.params || options.defaultParams || []
|
||||
// @ts-ignore
|
||||
fetchInstance.run(...params);
|
||||
fetchInstance.run(...params)
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
fetchInstance.cancel();
|
||||
});
|
||||
fetchInstance.cancel()
|
||||
})
|
||||
|
||||
return {
|
||||
...toRefs(fetchInstance.state),
|
||||
@@ -45,5 +45,5 @@ export function useRequestImplement<TData, TParams extends any[]>(
|
||||
refreshAsync: fetchInstance.refreshAsync.bind(fetchInstance),
|
||||
run: fetchInstance.run.bind(fetchInstance),
|
||||
runAsync: fetchInstance.runAsync.bind(fetchInstance),
|
||||
} as UseRequestResult<TData, TParams>;
|
||||
} as UseRequestResult<TData, TParams>
|
||||
}
|
||||
|
@@ -1,48 +1,48 @@
|
||||
type Timer = ReturnType<typeof setTimeout>;
|
||||
type CachedKey = string | number;
|
||||
type Timer = ReturnType<typeof setTimeout>
|
||||
type CachedKey = string | number
|
||||
|
||||
export interface CachedData<TData = any, TParams = any> {
|
||||
data: TData;
|
||||
params: TParams;
|
||||
time: number;
|
||||
data: TData
|
||||
params: TParams
|
||||
time: number
|
||||
}
|
||||
|
||||
interface RecordData extends CachedData {
|
||||
timer: Timer | undefined;
|
||||
timer: Timer | undefined
|
||||
}
|
||||
|
||||
const cache = new Map<CachedKey, RecordData>();
|
||||
const cache = new Map<CachedKey, RecordData>()
|
||||
|
||||
export const setCache = (key: CachedKey, cacheTime: number, cachedData: CachedData) => {
|
||||
const currentCache = cache.get(key);
|
||||
const currentCache = cache.get(key)
|
||||
if (currentCache?.timer) {
|
||||
clearTimeout(currentCache.timer);
|
||||
clearTimeout(currentCache.timer)
|
||||
}
|
||||
|
||||
let timer: Timer | undefined = undefined;
|
||||
let timer: Timer | undefined = undefined
|
||||
|
||||
if (cacheTime > -1) {
|
||||
// if cache out, clear it
|
||||
timer = setTimeout(() => {
|
||||
cache.delete(key);
|
||||
}, cacheTime);
|
||||
cache.delete(key)
|
||||
}, cacheTime)
|
||||
}
|
||||
|
||||
cache.set(key, {
|
||||
...cachedData,
|
||||
timer,
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
export const getCache = (key: CachedKey) => {
|
||||
return cache.get(key);
|
||||
};
|
||||
return cache.get(key)
|
||||
}
|
||||
|
||||
export const clearCache = (key?: string | string[]) => {
|
||||
if (key) {
|
||||
const cacheKeys = Array.isArray(key) ? key : [key];
|
||||
cacheKeys.forEach((cacheKey) => cache.delete(cacheKey));
|
||||
const cacheKeys = Array.isArray(key) ? key : [key]
|
||||
cacheKeys.forEach((cacheKey) => cache.delete(cacheKey))
|
||||
} else {
|
||||
cache.clear();
|
||||
cache.clear()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@@ -1,23 +1,23 @@
|
||||
type CachedKey = string | number;
|
||||
type CachedKey = string | number
|
||||
|
||||
const cachePromise = new Map<CachedKey, Promise<any>>();
|
||||
const cachePromise = new Map<CachedKey, Promise<any>>()
|
||||
|
||||
export const getCachePromise = (cacheKey: CachedKey) => {
|
||||
return cachePromise.get(cacheKey);
|
||||
};
|
||||
return cachePromise.get(cacheKey)
|
||||
}
|
||||
|
||||
export const setCachePromise = (cacheKey: CachedKey, promise: Promise<any>) => {
|
||||
// Should cache the same promise, cannot be promise.finally
|
||||
// Because the promise.finally will change the reference of the promise
|
||||
cachePromise.set(cacheKey, promise);
|
||||
cachePromise.set(cacheKey, promise)
|
||||
|
||||
// no use promise.finally for compatibility
|
||||
promise
|
||||
.then((res) => {
|
||||
cachePromise.delete(cacheKey);
|
||||
return res;
|
||||
cachePromise.delete(cacheKey)
|
||||
return res
|
||||
})
|
||||
.catch(() => {
|
||||
cachePromise.delete(cacheKey);
|
||||
});
|
||||
};
|
||||
cachePromise.delete(cacheKey)
|
||||
})
|
||||
}
|
||||
|
@@ -1,22 +1,22 @@
|
||||
type Listener = (data: any) => void;
|
||||
type Listener = (data: any) => void
|
||||
|
||||
const listeners: Record<string, Listener[]> = {};
|
||||
const listeners: Record<string, Listener[]> = {}
|
||||
|
||||
export const trigger = (key: string, data: any) => {
|
||||
if (listeners[key]) {
|
||||
listeners[key].forEach((item) => item(data));
|
||||
listeners[key].forEach((item) => item(data))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export const subscribe = (key: string, listener: Listener) => {
|
||||
if (!listeners[key]) {
|
||||
listeners[key] = [];
|
||||
listeners[key] = []
|
||||
}
|
||||
|
||||
listeners[key].push(listener);
|
||||
listeners[key].push(listener)
|
||||
|
||||
return function unsubscribe() {
|
||||
const index = listeners[key].indexOf(listener);
|
||||
listeners[key].splice(index, 1);
|
||||
};
|
||||
};
|
||||
const index = listeners[key].indexOf(listener)
|
||||
listeners[key].splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
@@ -2,4 +2,4 @@ export const isBrowser = !!(
|
||||
typeof window !== 'undefined' &&
|
||||
window.document &&
|
||||
window.document.createElement
|
||||
);
|
||||
)
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import { isBrowser } from './isBrowser';
|
||||
import { isBrowser } from './isBrowser'
|
||||
|
||||
export function isDocumentVisible(): boolean {
|
||||
if (isBrowser) {
|
||||
return document.visibilityState !== 'hidden';
|
||||
return document.visibilityState !== 'hidden'
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
@@ -1,2 +1,2 @@
|
||||
export const isFunction = (value: unknown): value is (...args: any) => any =>
|
||||
typeof value === 'function';
|
||||
typeof value === 'function'
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import { isBrowser } from './isBrowser';
|
||||
import { isBrowser } from './isBrowser'
|
||||
|
||||
export function isOnline(): boolean {
|
||||
if (isBrowser && typeof navigator.onLine !== 'undefined') {
|
||||
return navigator.onLine;
|
||||
return navigator.onLine
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
@@ -1,12 +1,12 @@
|
||||
export function limit(fn: any, timespan: number) {
|
||||
let pending = false;
|
||||
let pending = false
|
||||
|
||||
return (...args: any[]) => {
|
||||
if (pending) return;
|
||||
pending = true;
|
||||
fn(...args);
|
||||
if (pending) return
|
||||
pending = true
|
||||
fn(...args)
|
||||
setTimeout(() => {
|
||||
pending = false;
|
||||
}, timespan);
|
||||
};
|
||||
pending = false
|
||||
}, timespan)
|
||||
}
|
||||
}
|
||||
|
@@ -1,30 +1,30 @@
|
||||
import { isBrowser } from './isBrowser';
|
||||
import { isDocumentVisible } from './isDocumentVisible';
|
||||
import { isOnline } from './isOnline';
|
||||
import { isBrowser } from './isBrowser'
|
||||
import { isDocumentVisible } from './isDocumentVisible'
|
||||
import { isOnline } from './isOnline'
|
||||
|
||||
type Listener = () => void;
|
||||
type Listener = () => void
|
||||
|
||||
const listeners: Listener[] = [];
|
||||
const listeners: Listener[] = []
|
||||
|
||||
if (isBrowser) {
|
||||
const revalidate = () => {
|
||||
if (!isDocumentVisible() || !isOnline()) return;
|
||||
if (!isDocumentVisible() || !isOnline()) return
|
||||
for (let i = 0; i < listeners.length; i++) {
|
||||
const listener = listeners[i];
|
||||
listener();
|
||||
const listener = listeners[i]
|
||||
listener()
|
||||
}
|
||||
};
|
||||
window.addEventListener('visibilitychange', revalidate, false);
|
||||
window.addEventListener('focus', revalidate, false);
|
||||
}
|
||||
window.addEventListener('visibilitychange', revalidate, false)
|
||||
window.addEventListener('focus', revalidate, false)
|
||||
}
|
||||
|
||||
export default function subscribe(listener: Listener) {
|
||||
listeners.push(listener);
|
||||
listeners.push(listener)
|
||||
|
||||
return function unsubscribe() {
|
||||
const index = listeners.indexOf(listener);
|
||||
const index = listeners.indexOf(listener)
|
||||
if (index > -1) {
|
||||
listeners.splice(index, 1);
|
||||
listeners.splice(index, 1)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -1,25 +1,25 @@
|
||||
import { isBrowser } from './isBrowser';
|
||||
import { isDocumentVisible } from './isDocumentVisible';
|
||||
import { isBrowser } from './isBrowser'
|
||||
import { isDocumentVisible } from './isDocumentVisible'
|
||||
|
||||
type Listener = () => void;
|
||||
type Listener = () => void
|
||||
|
||||
const listeners: Listener[] = [];
|
||||
const listeners: Listener[] = []
|
||||
|
||||
if (isBrowser) {
|
||||
const revalidate = () => {
|
||||
if (!isDocumentVisible()) return;
|
||||
if (!isDocumentVisible()) return
|
||||
for (let i = 0; i < listeners.length; i++) {
|
||||
const listener = listeners[i];
|
||||
listener();
|
||||
const listener = listeners[i]
|
||||
listener()
|
||||
}
|
||||
};
|
||||
window.addEventListener('visibilitychange', revalidate, false);
|
||||
}
|
||||
window.addEventListener('visibilitychange', revalidate, false)
|
||||
}
|
||||
|
||||
export default function subscribe(listener: Listener) {
|
||||
listeners.push(listener);
|
||||
listeners.push(listener)
|
||||
return function unsubscribe() {
|
||||
const index = listeners.indexOf(listener);
|
||||
listeners.splice(index, 1);
|
||||
};
|
||||
const index = listeners.indexOf(listener)
|
||||
listeners.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
@@ -1,60 +1,60 @@
|
||||
import { shallowRef, unref } from 'vue';
|
||||
import { shallowRef, unref } from 'vue'
|
||||
|
||||
interface UseScrollToOptions {
|
||||
el: any;
|
||||
to: number;
|
||||
duration?: number;
|
||||
callback?: () => any;
|
||||
el: any
|
||||
to: number
|
||||
duration?: number
|
||||
callback?: () => any
|
||||
}
|
||||
|
||||
function easeInOutQuad(t: number, b: number, c: number, d: number) {
|
||||
t /= d / 2;
|
||||
t /= d / 2
|
||||
if (t < 1) {
|
||||
return (c / 2) * t * t + b;
|
||||
return (c / 2) * t * t + b
|
||||
}
|
||||
t--;
|
||||
return (-c / 2) * (t * (t - 2) - 1) + b;
|
||||
t--
|
||||
return (-c / 2) * (t * (t - 2) - 1) + b
|
||||
}
|
||||
|
||||
function move(el: HTMLElement, amount: number) {
|
||||
el.scrollTop = amount;
|
||||
el.scrollTop = amount
|
||||
}
|
||||
|
||||
const position = (el: HTMLElement) => {
|
||||
return el.scrollTop;
|
||||
};
|
||||
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 isActiveRef = shallowRef(false)
|
||||
const start = position(el)
|
||||
const change = to - start
|
||||
const increment = 20
|
||||
let currentTime = 0
|
||||
|
||||
const animateScroll = function () {
|
||||
if (!unref(isActiveRef)) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
currentTime += increment;
|
||||
const val = easeInOutQuad(currentTime, start, change, duration);
|
||||
move(el, val);
|
||||
currentTime += increment
|
||||
const val = easeInOutQuad(currentTime, start, change, duration)
|
||||
move(el, val)
|
||||
if (currentTime < duration && unref(isActiveRef)) {
|
||||
requestAnimationFrame(animateScroll);
|
||||
requestAnimationFrame(animateScroll)
|
||||
} else {
|
||||
if (callback && typeof callback === 'function') {
|
||||
callback();
|
||||
callback()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
const run = () => {
|
||||
isActiveRef.value = true;
|
||||
animateScroll();
|
||||
};
|
||||
isActiveRef.value = true
|
||||
animateScroll()
|
||||
}
|
||||
|
||||
const stop = () => {
|
||||
isActiveRef.value = false;
|
||||
};
|
||||
isActiveRef.value = false
|
||||
}
|
||||
|
||||
return { start: run, stop };
|
||||
return { start: run, stop }
|
||||
}
|
||||
|
||||
export { useScrollTo, type UseScrollToOptions };
|
||||
export { useScrollTo, type UseScrollToOptions }
|
||||
|
@@ -1,40 +1,40 @@
|
||||
import { type AnyFunction } from '@vben/types';
|
||||
import { tryOnMounted, tryOnUnmounted, useDebounceFn } from '@vueuse/core';
|
||||
import { type AnyFunction } from '@vben/types'
|
||||
import { tryOnMounted, tryOnUnmounted, useDebounceFn } from '@vueuse/core'
|
||||
|
||||
interface UseWindowSizeOptions {
|
||||
wait?: number;
|
||||
once?: boolean;
|
||||
immediate?: boolean;
|
||||
listenerOptions?: AddEventListenerOptions | boolean;
|
||||
wait?: number
|
||||
once?: boolean
|
||||
immediate?: boolean
|
||||
listenerOptions?: AddEventListenerOptions | boolean
|
||||
}
|
||||
|
||||
function useWindowSizeFn(fn: AnyFunction, options: UseWindowSizeOptions = {}) {
|
||||
const { wait = 150, immediate } = options;
|
||||
const { wait = 150, immediate } = options
|
||||
let handler = () => {
|
||||
fn();
|
||||
};
|
||||
const handleSize = useDebounceFn(handler, wait);
|
||||
handler = handleSize;
|
||||
fn()
|
||||
}
|
||||
const handleSize = useDebounceFn(handler, wait)
|
||||
handler = handleSize
|
||||
|
||||
const start = () => {
|
||||
if (immediate) {
|
||||
handler();
|
||||
handler()
|
||||
}
|
||||
window.addEventListener('resize', handler);
|
||||
};
|
||||
window.addEventListener('resize', handler)
|
||||
}
|
||||
|
||||
const stop = () => {
|
||||
window.removeEventListener('resize', handler);
|
||||
};
|
||||
window.removeEventListener('resize', handler)
|
||||
}
|
||||
|
||||
tryOnMounted(() => {
|
||||
start();
|
||||
});
|
||||
start()
|
||||
})
|
||||
|
||||
tryOnUnmounted(() => {
|
||||
stop();
|
||||
});
|
||||
return { start, stop };
|
||||
stop()
|
||||
})
|
||||
return { start, stop }
|
||||
}
|
||||
|
||||
export { useWindowSizeFn, type UseWindowSizeOptions };
|
||||
export { useWindowSizeFn, type UseWindowSizeOptions }
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { defineBuildConfig } from 'unbuild';
|
||||
import { defineBuildConfig } from 'unbuild'
|
||||
|
||||
export default defineBuildConfig({
|
||||
clean: true,
|
||||
@@ -7,4 +7,4 @@ export default defineBuildConfig({
|
||||
rollup: {
|
||||
emitCJS: true,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
@@ -1 +1 @@
|
||||
export * from './utils';
|
||||
export * from './utils'
|
||||
|
@@ -1,49 +1,49 @@
|
||||
/**
|
||||
* 任意类型的异步函数
|
||||
*/
|
||||
type AnyPromiseFunction = (...arg: any[]) => PromiseLike<any>;
|
||||
type AnyPromiseFunction = (...arg: any[]) => PromiseLike<any>
|
||||
|
||||
/**
|
||||
* 任意类型的普通函数
|
||||
*/
|
||||
type AnyNormalFunction = (...arg: any[]) => any;
|
||||
type AnyNormalFunction = (...arg: any[]) => any
|
||||
|
||||
/**
|
||||
* 任意类型的函数
|
||||
*/
|
||||
type AnyFunction = AnyNormalFunction | AnyPromiseFunction;
|
||||
type AnyFunction = AnyNormalFunction | AnyPromiseFunction
|
||||
|
||||
/**
|
||||
* T | null 包装
|
||||
*/
|
||||
type Nullable<T> = T | null;
|
||||
type Nullable<T> = T | null
|
||||
|
||||
/**
|
||||
* T | Not null 包装
|
||||
*/
|
||||
type NonNullable<T> = T extends null | undefined ? never : T;
|
||||
type NonNullable<T> = T extends null | undefined ? never : T
|
||||
|
||||
/**
|
||||
* 字符串类型对象
|
||||
*/
|
||||
type Recordable<T = any> = Record<string, T>;
|
||||
type Recordable<T = any> = Record<string, T>
|
||||
|
||||
/**
|
||||
* 字符串类型对象(只读)
|
||||
*/
|
||||
interface ReadonlyRecordable<T = any> {
|
||||
readonly [key: string]: T;
|
||||
readonly [key: string]: T
|
||||
}
|
||||
|
||||
/**
|
||||
* setTimeout 返回值类型
|
||||
*/
|
||||
type TimeoutHandle = ReturnType<typeof setTimeout>;
|
||||
type TimeoutHandle = ReturnType<typeof setTimeout>
|
||||
|
||||
/**
|
||||
* setInterval 返回值类型
|
||||
*/
|
||||
type IntervalHandle = ReturnType<typeof setInterval>;
|
||||
type IntervalHandle = ReturnType<typeof setInterval>
|
||||
|
||||
export {
|
||||
type AnyFunction,
|
||||
@@ -55,4 +55,4 @@ export {
|
||||
type ReadonlyRecordable,
|
||||
type Recordable,
|
||||
type TimeoutHandle,
|
||||
};
|
||||
}
|
||||
|
Reference in New Issue
Block a user