提交 d9b19600 编写于 作者: V vben

refactor(hooks): introduce vueuse, delete duplicate hooks

上级 ecfb702b
## Wip
### ✨ Refactor
- 重构 hook,引入 `@vueuse`,删除其中已有的`hook`,优化现有的 hook
- `useEvent` 更名->`useEventListener`
### ✨ Features
- 表单项的`componentsProps`支持函数类型
......@@ -16,6 +21,7 @@
- 修复多个富文本编辑器只显示一个
- 修复登录过期后重新登录未跳转原来页面的
- 修复 window 系统动态引入错误
- 修复页面类型错误
## 2.0.0-rc.9 (2020-11-9)
......
......@@ -13,7 +13,7 @@
import moment from 'moment';
import 'moment/dist/locale/zh-cn';
import { useConfigProvider, useInitAppConfigStore, useListenerNetWork } from './useApp';
import { useConfigProvider, useInitAppConfigStore } from './useApp';
import { useLockPage } from '/@/hooks/web/useLockPage';
import { useSetting } from '/@/hooks/core/useSetting';
......@@ -25,8 +25,6 @@
setup() {
// Initialize application settings
useInitAppConfigStore();
// Initialize network monitoring
useListenerNetWork();
// Initialize breakpoint monitoring
createBreakpointListen();
// Get system configuration
......
......@@ -11,7 +11,7 @@
<script lang="ts">
import { defineComponent, inject, ref, onMounted, unref } from 'vue';
import { useRouter } from 'vue-router';
import { useEvent } from '/@/hooks/event/useEvent';
import { useEventListener } from '/@/hooks/event/useEventListener';
export default defineComponent({
name: 'BreadcrumbItem',
......@@ -42,7 +42,7 @@
onMounted(() => {
const link = unref(linkRef);
if (!link) return;
useEvent({
useEventListener({
el: link,
listener: () => {
const { to } = props;
......
......@@ -22,8 +22,7 @@
import { defineComponent, reactive, onMounted, ref, toRef, toRefs } from 'vue';
import { Skeleton } from 'ant-design-vue';
import { useTimeout } from '/@/hooks/core/useTimeout';
import { useIntersectionObserver } from '/@/hooks/event/useIntersectionObserver';
import { useTimeoutFn, useIntersectionObserver } from '@vueuse/core';
interface State {
isInit: boolean;
loading: boolean;
......@@ -93,7 +92,7 @@
function immediateInit() {
const { timeout } = props;
timeout &&
useTimeout(() => {
useTimeoutFn(() => {
init();
}, timeout);
}
......@@ -101,7 +100,7 @@
function init() {
state.loading = true;
useTimeout(() => {
useTimeoutFn(() => {
if (state.isInit) return;
state.isInit = true;
emit('init');
......
......@@ -32,7 +32,8 @@
import { triggerWindowResize } from '/@/utils/event/triggerWindowResizeEvent';
// hook
import { useTimeout } from '/@/hooks/core/useTimeout';
import { useTimeoutFn } from '@vueuse/core';
export default defineComponent({
components: {
Skeleton,
......@@ -89,7 +90,7 @@
if (props.triggerWindowResize) {
// 这里200毫秒是因为展开有动画,
useTimeout(triggerWindowResize, 200);
useTimeoutFn(triggerWindowResize, 200);
}
}
return {
......
......@@ -6,15 +6,13 @@
<script lang="ts">
import { defineComponent, reactive, computed, watch, onMounted, unref, toRef } from 'vue';
import { countToProps } from './props';
import { useRaf } from '/@/hooks/event/useRaf';
import { isNumber } from '/@/utils/is';
import { requestAnimationFrame, cancelAnimationFrame } from '/@/utils/animation';
export default defineComponent({
name: 'CountTo',
props: countToProps,
emits: ['mounted', 'callback'],
setup(props, { emit }) {
const { requestAnimationFrame, cancelAnimationFrame } = useRaf();
const state = reactive<{
localStartVal: number;
printVal: number | null;
......
import { Modal } from 'ant-design-vue';
import { defineComponent, watchEffect } from 'vue';
import { basicProps } from './props';
import { useTimeout } from '/@/hooks/core/useTimeout';
import { useTimeoutFn } from '@vueuse/core';
import { extendSlots } from '/@/utils/helper/tsxHelper';
export default defineComponent({
......@@ -99,7 +99,7 @@ export default defineComponent({
if (!props.visible) {
return;
}
useTimeout(() => {
useTimeoutFn(() => {
handleDrag();
}, 30);
});
......
......@@ -14,8 +14,7 @@ import {
} from 'vue';
import { Spin } from 'ant-design-vue';
import { useWindowSizeFn } from '/@/hooks/event/useWindowSize';
// import { useTimeout } from '/@/hooks/core/useTimeout';
import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
import { getSlot } from '/@/utils/helper/tsxHelper';
import { useElResize } from '/@/hooks/event/useElResize';
......@@ -126,17 +125,6 @@ export default defineComponent({
}
await nextTick();
const spinEl = unref(spinRef);
// if (!spinEl) {
// useTimeout(() => {
// // retry
// if (tryCount < 3) {
// setModalHeight();
// }
// tryCount++;
// }, 10);
// return;
// }
// tryCount = 0;
const spinContainerEl = spinEl.$el.querySelector('.ant-spin-container') as HTMLElement;
if (!spinContainerEl) return;
......
......@@ -64,7 +64,7 @@
import { useTableScroll } from './hooks/useTableScroll';
import { provideTable } from './hooks/useProvinceTable';
import { useEvent } from '/@/hooks/event/useEvent';
import { useEventListener } from '/@/hooks/event/useEventListener';
import { basicProps } from './props';
import { ROW_KEY } from './const';
import './style/index.less';
......@@ -245,7 +245,7 @@
}
const bodyDomList = tableEl.$el.querySelectorAll('.ant-table-body') as HTMLDivElement[];
const bodyDom = bodyDomList[0];
useEvent({
useEventListener({
el: bodyDom,
name: 'scroll',
listener: () => {
......
......@@ -3,7 +3,7 @@ import type { PaginationProps } from '../types/pagination';
import { watch, ref, unref, ComputedRef, computed, onMounted, Ref } from 'vue';
import { useTimeout } from '/@/hooks/core/useTimeout';
import { useTimeoutFn } from '@vueuse/core';
import { buildUUID } from '/@/utils/uuid';
import { isFunction, isBoolean } from '/@/utils/is';
......@@ -145,7 +145,7 @@ export function useDataSource(
}
onMounted(() => {
// 转异步任务
useTimeout(() => {
useTimeoutFn(() => {
unref(propsRef).immediate && fetch();
}, 0);
});
......
......@@ -6,7 +6,7 @@ import { injectModal } from '/@/components/Modal/src/provideModal';
import { getViewportOffset } from '/@/utils/domUtils';
import { isBoolean } from '/@/utils/is';
import { useWindowSizeFn } from '/@/hooks/event/useWindowSize';
import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
import { useProps } from './useProps';
export function useTableScroll(refProps: ComputedRef<BasicTableProps>, tableElRef: Ref<any>) {
......@@ -110,17 +110,6 @@ export function useTableScroll(refProps: ComputedRef<BasicTableProps>, tableElRe
nextTick(() => {
calcTableHeight();
});
// const hasFixedLeft = (unref(propsRef).columns || []).some((item) => item.fixed === 'left');
// // TODO antv table问题情况太多,只能先用下面方式定时器hack
// useTimeout(() => {
// calcTableHeight(() => {
// // 有左侧固定列的时候才有问题
// hasFixedLeft &&
// useTimeout(() => {
// triggerWindowResize();
// }, 300);
// });
// }, 200);
}
});
const getScrollRef = computed(() => {
......
import { defineComponent, ref, computed, unref, reactive, watch, watchEffect } from 'vue';
import { useTimeout } from '/@/hooks/core/useTimeout';
import { useEvent } from '/@/hooks/event/useEvent';
import { useTimeoutFn } from '@vueuse/core';
import { useEventListener } from '/@/hooks/event/useEventListener';
import { basicProps } from './props';
import { getSlot } from '/@/utils/helper/tsxHelper';
import './DragVerify.less';
......@@ -91,7 +91,7 @@ export default defineComponent({
return (e as MouseEvent).pageX || (e as TouchEvent).touches[0].pageX;
}
useEvent({
useEventListener({
el: document,
name: 'mouseup',
listener: () => {
......@@ -201,7 +201,7 @@ export default defineComponent({
const contentEl = unref(contentElRef);
if (!actionEl || !barEl || !contentEl) return;
state.toLeft = true;
useTimeout(() => {
useTimeoutFn(() => {
state.toLeft = false;
actionEl.style.left = '0';
barEl.style.width = '0';
......
import type { MoveData, DragVerifyActionType } from './types';
import { defineComponent, computed, unref, reactive, watch, ref, getCurrentInstance } from 'vue';
import { useTimeout } from '/@/hooks/core/useTimeout';
import { useTimeoutFn } from '@vueuse/core';
import BasicDragVerify from './DragVerify';
......@@ -86,7 +86,7 @@ export default defineComponent({
if (Math.abs(randomRotate - currentRotate) >= (diffDegree || 20)) {
state.imgStyle = hackCss('transform', `rotateZ(${randomRotate}deg)`);
state.toOrigin = true;
useTimeout(() => {
useTimeoutFn(() => {
state.toOrigin = false;
state.showTip = true;
// 时间与动画时间保持一致
......
<script lang="tsx">
import { defineComponent, ref, unref } from 'vue';
import { BasicModal } from '/@/components/Modal/index';
import { useTimeout } from '/@/hooks/core/useTimeout';
import { useTimeoutFn } from '@vueuse/core';
import { RotateDragVerify, DragVerifyActionType } from '/@/components/Verify/index';
export default defineComponent({
......@@ -11,7 +11,7 @@
const dragRef = ref<DragVerifyActionType | null>(null);
function handleSuccess() {
useTimeout(() => {
useTimeoutFn(() => {
emit('success');
const dragEl = unref(dragRef);
if (dragEl) {
......
import { defineComponent, computed, ref, unref, reactive, onMounted, watch, nextTick } from 'vue';
import { useEvent } from '/@/hooks/event/useEvent';
import { useEventListener } from '/@/hooks/event/useEventListener';
import { convertToUnit } from '/@/components/util';
import { props as basicProps } from './props';
......@@ -109,7 +109,7 @@ export default defineComponent({
if (!wrapEl) {
return;
}
useEvent({
useEventListener({
el: wrapEl,
name: 'scroll',
listener: onScroll,
......
import { ref, watchEffect, Ref } from 'vue';
/**
* Handle overlapping async evaluations
*
* @param cancelCallback The provided callback is invoked when a re-evaluation of the computed value is triggered before the previous one finished
*/
export type AsyncComputedOnCancel = (cancelCallback: () => void) => void;
/**
* A two-item tuple with the first item being a ref to the computed value and the second item holding a boolean ref, indicating whether the async computed value is currently (re-)evaluated
*/
export type AsyncComputedResult<T> = [Ref<T>, Ref<boolean>];
/**
* Create an asynchronous computed dependency
*
* @param evaluationCallback The promise-returning callback which generates the computed value
* @param defaultValue A default value, used until the first evaluation finishes
*/
export function asyncComputed<T>(
evaluationCallback: (onCancel: AsyncComputedOnCancel) => T | Promise<T>,
defaultValue?: T
): AsyncComputedResult<T> {
let counter = 0;
const current = ref(defaultValue) as Ref<T>;
const evaluating = ref<boolean>(false);
watchEffect(async (onInvalidate: Fn) => {
counter++;
const counterAtBeginning = counter;
let hasFinished = false;
try {
// Defer initial setting of `evaluating` ref
// to avoid having it as a dependency
Promise.resolve().then(() => {
evaluating.value = true;
});
const result = await evaluationCallback((cancelCallback) => {
onInvalidate(() => {
evaluating.value = false;
if (!hasFinished) cancelCallback();
});
});
if (counterAtBeginning === counter) current.value = result;
} finally {
evaluating.value = false;
hasFinished = true;
}
});
return [current, evaluating];
}
import { ref } from 'vue';
export function useCounter(initialValue = 0) {
const count = ref(initialValue);
const inc = (delta = 1) => (count.value += delta);
const dec = (delta = 1) => (count.value -= delta);
const get = () => count.value;
const set = (val: number) => (count.value = val);
const reset = (val = initialValue) => {
initialValue = val;
return set(val);
};
return { count, inc, dec, get, set, reset };
}
import { isFunction } from '/@/utils/is';
import { Ref, watch } from 'vue';
import { useTimeoutRef } from '/@/hooks/core/useTimeoutRef';
type TimeoutFnResult = [Fn<void>, Fn<void>, Ref<boolean>];
export function useTimeout(handle: Fn<any>, wait: number): TimeoutFnResult {
if (!isFunction(handle)) {
throw new Error('handle is not Function!');
}
const [readyRef, clear, runAgain] = useTimeoutRef(wait);
watch(
readyRef,
(maturity) => {
maturity && handle();
},
{ immediate: false }
);
return [clear, runAgain, readyRef];
}
import { Ref, ref } from 'vue';
import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
export type TimeoutResult = [Ref<boolean>, Fn<void>, Fn<void>];
export function useTimeoutRef(wait: number): TimeoutResult {
const readyRef = ref(false);
let timer: ReturnType<typeof setTimeout> | undefined;
function clear(): void {
readyRef.value = false;
timer && window.clearTimeout(timer);
}
function openTimer(): void {
clear();
timer = setTimeout(() => {
readyRef.value = true;
}, wait);
}
openTimer();
tryOnUnmounted(clear);
return [readyRef, clear, openTimer];
}
import { ref, computed, Ref, unref } from 'vue';
import { useEvent } from './useEvent';
import { ref, computed, ComputedRef, unref } from 'vue';
import { useEventListener } from '/@/hooks/event/useEventListener';
import { screenMap, sizeEnum, screenEnum } from '/@/enums/breakpointEnum';
let globalScreenRef: Ref<sizeEnum | undefined>;
let globalWidthRef: Ref<number>;
let globalRealWidthRef: Ref<number>;
let globalScreenRef: ComputedRef<sizeEnum | undefined>;
let globalWidthRef: ComputedRef<number>;
let globalRealWidthRef: ComputedRef<number>;
export function useBreakpoint() {
return {
......@@ -43,7 +43,7 @@ export function createBreakpointListen(fn?: Fn) {
realWidthRef.value = width;
}
useEvent({
useEventListener({
el: window,
name: 'resize',
listener: () => {
......
import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
import EventHub from '/@/utils/eventHub';
const eventHub = new EventHub();
export function useEventHub(): EventHub {
tryOnUnmounted(() => {
eventHub.clear();
});
return eventHub;
}
......@@ -15,7 +15,7 @@ export interface UseEventParams {
isDebounce?: boolean;
wait?: number;
}
export function useEvent({
export function useEventListener({
el = window,
name,
listener,
......
import { Ref, watchEffect, ref } from 'vue';
interface IntersectionObserverProps {
target: Ref<Element | null | undefined>;
root?: Ref<Element | null | undefined>;
onIntersect: IntersectionObserverCallback;
rootMargin?: string;
threshold?: number;
}
export function useIntersectionObserver({
target,
root,
onIntersect,
rootMargin = '0px',
threshold = 0.1,
}: IntersectionObserverProps) {
let cleanup = () => {};
const observer: Ref<Nullable<IntersectionObserver>> = ref(null);
const stopEffect = watchEffect(() => {
cleanup();
observer.value = new IntersectionObserver(onIntersect, {
root: root ? root.value : null,
rootMargin,
threshold,
});
const current = target.value;
current && observer.value.observe(current);
cleanup = () => {
if (observer.value) {
observer.value.disconnect();
target.value && observer.value.unobserve(target.value);
}
};
});
return {
observer,
stop: () => {
cleanup();
stopEffect();
},
};
}
import { ref } from 'vue';
import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
function getTimestamp() {
return +Date.now();
}
export function useNow() {
const now = ref(getTimestamp());
let started = false;
const update = () => {
requestAnimationFrame(() => {
now.value = getTimestamp();
if (started) update();
});
};
const start = () => {
if (!started) {
started = true;
update();
}
};
const stop = () => {
started = false;
};
start();
tryOnUnmounted(stop);
return now;
}
import { isServer } from '/@/utils/is';
import { onUnmounted, getCurrentInstance } from 'vue';
let lastTime = 0;
const prefixes = 'webkit moz ms o'.split(' '); // Each browser prefix
let requestAnimationFrame: any;
let cancelAnimationFrame: any;
/* eslint-disable-next-line */
const NO_LOOP = () => {};
const getWindowFrame = (name: string) => {
return name as any;
};
if (isServer) {
requestAnimationFrame = cancelAnimationFrame = NO_LOOP;
} else {
requestAnimationFrame = window.requestAnimationFrame;
cancelAnimationFrame = window.cancelAnimationFrame;
let prefix;
for (let i = 0; i < prefixes.length; i++) {
if (requestAnimationFrame && cancelAnimationFrame) {
break;
}
prefix = prefixes[i];
requestAnimationFrame =
requestAnimationFrame || window[getWindowFrame(prefix + 'RequestAnimationFrame')];
cancelAnimationFrame =
cancelAnimationFrame ||
window[getWindowFrame(prefix + 'CancelAnimationFrame')] ||
window[getWindowFrame(prefix + 'CancelRequestAnimationFrame')];
}
// If the current browser does not support requestAnimationFrame and cancelAnimationFrame, it will fall back to setTimeout
if (!requestAnimationFrame || !cancelAnimationFrame) {
requestAnimationFrame = function (callback: Fn) {
const currTime = new Date().getTime();
const timeToCall = Math.max(0, 16 - (currTime - lastTime));
const id = window.setTimeout(() => {
/* eslint-disable-next-line */
callback(currTime + timeToCall);
}, timeToCall);
lastTime = currTime + timeToCall;
return id;
};
cancelAnimationFrame = function (id: number) {
window.clearTimeout(id);
};
}
}
export function useRaf() {
// if (getCurrentInstance()) {
// onUnmounted(() => {
// cancelAnimationFrame();
// });
// }
return { requestAnimationFrame, cancelAnimationFrame };
}
export function useRafFn(fn: (...arg: any) => any, options: { immediate?: boolean } = {}) {
const { immediate = false } = options;
let started = false;
let id: ReturnType<typeof window.requestAnimationFrame>;
function loop() {
if (!started) return;
fn();
id = requestAnimationFrame(loop);
}
function start() {
if (!started) {
started = true;
loop();
}
}
function stop() {
started = false;
}
if (immediate) {
start();
}
if (getCurrentInstance()) {
onUnmounted(() => {
cancelAnimationFrame(id);
stop();
});
}
return { stop, start };
}
import { useRaf } from '/@/hooks/event/useRaf';
import { isFunction, isUnDef } from '/@/utils/is';
import { ref, unref } from 'vue';
import { requestAnimationFrame } from '/@/utils/animation';
export interface ScrollToParams {
el: HTMLElement;
to: number;
......@@ -30,7 +31,6 @@ export function useScrollTo({ el, to, duration = 500, callback }: ScrollToParams
const increment = 20;
let currentTime = 0;
duration = isUnDef(duration) ? 500 : duration;
const { requestAnimationFrame } = useRaf();
const animateScroll = function () {
if (!unref(isActiveRef)) {
......
import { tryOnMounted, tryOnUnmounted } from '/@/utils/helper/vueHelper';
import { ref } from 'vue';
import { useDebounce } from '/@/hooks/core/useDebounce';
......@@ -37,22 +36,3 @@ export function useWindowSizeFn<T>(fn: Fn<T>, wait = 150, options?: WindowSizeOp
});
return [start, stop];
}
export const useWindowSize = (wait = 150, options?: WindowSizeOptions) => {
const widthRef = ref(0);
const heightRef = ref(0);
function setSize() {
widthRef.value = window.innerWidth;
heightRef.value = window.innerHeight;
}
setSize();
const handler = () => {
setSize();
};
useWindowSizeFn(handler, wait, options);
return { widthRef: widthRef, heightRef: heightRef };
};
import { reactive } from 'vue';
export function createGlobalState<T extends object>(factory: () => T) {
let state: T;
return () => {
if (!state) {
state = reactive(factory()) as T;
}
return state;
};
}
import { useTimeout } from '/@/hooks/core/useTimeout';
import { useTimeoutFn } from '@vueuse/core';
import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
import { unref, Ref, nextTick } from 'vue';
......@@ -9,7 +9,7 @@ export function useApexCharts(elRef: Ref<HTMLDivElement>) {
function setOptions(options: any) {
nextTick(() => {
useTimeout(() => {
useTimeoutFn(() => {
const el = unref(elRef);
if (!el || !unref(el)) return;
......
import { ref, Ref, unref } from 'vue';
import { useEvent } from '/@/hooks/event/useEvent';
import { useEventListener } from '/@/hooks/event/useEventListener';
export function useClickOutside<T extends HTMLElement>(
containerRef: Ref<T>,
onClickOutside: (e: MouseEvent | TouchEvent) => void
) {
const isTouchRef = ref(false);
useEvent({
useEventListener({
el: document,
name: 'touchend',
listener: handler,
options: true,
});
useEvent({
useEventListener({
el: document,
name: 'click',
listener: handler,
......
// import { ref, Ref, isRef, watch } from '@vue/runtime-dom';
// TODO 打开注释会造成热更新失效,待排查
// export default function useCssVar(prop: string, refEl?: Ref<HTMLElement | null>) {
// const refVar = ref('');
// let el: HTMLElement = document.documentElement;
// if (isRef(refEl)) {
// watch(
// refEl,
// () => {
// if (refEl.value) {
// el = refEl.value as HTMLElement;
// refVar.value = getComputedStyle(el).getPropertyValue(prop);
// }
// },
// { immediate: true }
// );
// } else {
// refVar.value = getComputedStyle(el).getPropertyValue(prop);
// }
// watch(
// refVar,
// (val) => {
// el && el.style.setProperty(prop, val);
// },
// { immediate: true }
// );
// return refVar;
// }
export function getCssVar(prop: string, dom = document.documentElement) {
return getComputedStyle(dom).getPropertyValue(prop);
}
export function setCssVar(prop: string, val: any, dom = document.documentElement) {
dom.style.setProperty(prop, val);
}
import { useTimeout } from '/@/hooks/core/useTimeout';
import { useTimeoutFn } from '@vueuse/core';
import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
import { unref, Ref, nextTick } from 'vue';
import type { EChartOption, ECharts } from 'echarts';
import echarts from 'echarts';
import { useDebounce } from '/@/hooks/core/useDebounce';
import { useEvent } from '/@/hooks/event/useEvent';
import { useEventListener } from '/@/hooks/event/useEventListener';
import { useBreakpoint } from '/@/hooks/event/useBreakpoint';
export type { EChartOption, ECharts };
......@@ -26,7 +26,7 @@ export function useECharts(
return;
}
chartInstance = echarts.init(el, theme);
const { removeEvent } = useEvent({
const { removeEvent } = useEventListener({
el: window,
name: 'resize',
listener: resizeFn,
......@@ -34,7 +34,7 @@ export function useECharts(
removeResizeFn = removeEvent;
const { widthRef, screenEnum } = useBreakpoint();
if (unref(widthRef) <= screenEnum.MD) {
useTimeout(() => {
useTimeoutFn(() => {
resizeFn();
}, 30);
}
......@@ -42,7 +42,7 @@ export function useECharts(
function setOptions(options: any, clear = true) {
nextTick(() => {
useTimeout(() => {
useTimeoutFn(() => {
if (!chartInstance) {
init();
......
import { createStorage } from '/@/utils/storage';
export function useLocalStorage() {
return createStorage(localStorage);
}
import type { Ref } from 'vue';
import { ref, watch } from 'vue';
import { tryOnMounted, tryOnUnmounted } from '/@/utils/helper/vueHelper';
import { isBoolean } from '/@/utils/is';
const ON_LINE = 'online';
const OFF_LINE = 'offline';
export function useNetWork({
onLineFn,
offLineFn,
}: {
onLineFn?: () => void;
offLineFn?: () => void;
}) {
const onLineRef = ref(navigator.onLine);
// Disconnect time
const offlineAt: Ref<number | undefined> = ref(undefined);
watch(
() => onLineRef.value,
(onLine, oldValue): void => {
if (isBoolean(oldValue) && !oldValue && onLine) {
onLineFn && onLineFn();
} else if (isBoolean(onLine) && !onLine && oldValue) {
// Network to no network
offlineAt.value = Date.now();
offLineFn && offLineFn();
}
},
{
immediate: false,
}
);
const handler = (e: Event) => {
const { type } = e;
onLineRef.value = type === ON_LINE;
};
tryOnMounted(() => {
window.addEventListener(ON_LINE, handler);
window.addEventListener(OFF_LINE, handler);
});
tryOnUnmounted(() => {
window.removeEventListener(ON_LINE, handler);
window.removeEventListener(OFF_LINE, handler);
});
return {
onLineRef,
};
}
import { createStorage } from '/@/utils/storage';
export function useSessionStorage() {
return createStorage(sessionStorage);
}
import { useTimeout } from '/@/hooks/core/useTimeout';
import { useTimeoutFn } from '@vueuse/core';
import { PageEnum } from '/@/enums/pageEnum';
import { TabItem, tabStore } from '/@/store/modules/tab';
import { appStore } from '/@/store/modules/app';
......@@ -98,7 +98,7 @@ export function useTabs() {
const to = getTo(path);
if (!to) return;
useTimeout(() => {
useTimeoutFn(() => {
tabStore.addTabByPathAction();
}, 0);
const { replace, query = {}, params = {} } = opt || {};
......
import type { Ref } from 'vue';
import { ref, watch } from 'vue';
import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
import { isString } from '/@/utils/is';
export function useTitle(overrideTitle: string | null = null): Ref<string | null> {
const title = ref<string | null>(isString(overrideTitle) ? overrideTitle : document.title);
const observer = new MutationObserver((m) => {
title.value = m[0].target.textContent;
});
watch(
title,
(t, o) => {
if (isString(t) && t !== o) {
document.title = t;
}
},
{
immediate: true,
flush: 'sync',
}
);
const titleElement = document.querySelector('title')!;
observer.observe(titleElement, { childList: true });
tryOnUnmounted(() => {
observer.disconnect();
});
return title;
}
import { ref, onUnmounted, computed } from '@vue/runtime-dom';
import { isDef } from '/@/utils/is';
export default function useVisibilityState() {
const refVisibility = ref(true);
if (isDef(document) && isDef(document.visibilityState)) {
const setVisibility = () => {
refVisibility.value = document.visibilityState === 'visible';
};
document.addEventListener('visibilitychange', setVisibility, false);
onUnmounted(() => {
document.removeEventListener('visibilitychange', setVisibility);
});
}
return computed(() => refVisibility.value);
}
......@@ -19,7 +19,7 @@ import {
import { useFullscreen } from '/@/hooks/web/useFullScreen';
import { useTabs } from '/@/hooks/web/useTabs';
import { useWindowSizeFn } from '/@/hooks/event/useWindowSize';
import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
import { useRouter } from 'vue-router';
import { useModal } from '/@/components/Modal';
......
......@@ -8,7 +8,7 @@
import { computed, defineComponent, PropType, ref, watch } from 'vue';
// hooks
import { useSetting } from '/@/hooks/core/useSetting';
import { useTimeout } from '/@/hooks/core/useTimeout';
import { useTimeoutFn } from '@vueuse/core';
import { useGo } from '/@/hooks/web/usePage';
import { PageEnum } from '/@/enums/pageEnum';
......@@ -41,7 +41,7 @@
() => props.showTitle,
(show: boolean) => {
if (show) {
useTimeout(() => {
useTimeoutFn(() => {
showRef.value = show;
}, 280);
} else {
......
......@@ -128,9 +128,6 @@ const setting: ProjectConfig = {
// 是否开启登录安全校验
openLoginVerify: true,
// 是否监听网络变化
listenNetWork: false,
// 是否开启页面切换loading
openPageLoading: true,
......
import { setCssVar } from '/@/hooks/web/useCssVar';
import { isHexColor, colorIsDark, lighten, darken } from '/@/utils/color';
import { appStore } from '/@/store/modules/app';
import { MenuThemeEnum } from '/@/enums/menuEnum';
......@@ -12,6 +11,10 @@ const SIDER_DARK_DARKEN_BG_COLOR = '--sider-dark-darken-bg-color';
const SIDER_LIGHTEN_1_BG_COLOR = '--sider-dark-lighten-1-bg-color';
const SIDER_LIGHTEN_2_BG_COLOR = '--sider-dark-lighten-2-bg-color';
export function setCssVar(prop: string, val: any, dom = document.documentElement) {
dom.style.setProperty(prop, val);
}
function toggleClass(flag: boolean, clsName: string) {
const body = document.body;
let { className } = body;
......
......@@ -101,8 +101,6 @@ export interface ProjectConfig {
routerTransition: RouterTransitionEnum;
// 是否开启登录安全校验
openLoginVerify: boolean;
// 是否监听网络变化
listenNetWork: boolean;
// 是否开启页面切换loading
openPageLoading: boolean;
// 是否开启回到顶部
......
......@@ -17,11 +17,6 @@ import {
} from '/@/setup/theme';
import { appStore } from '/@/store/modules/app';
import { useNetWork } from '/@/hooks/web/useNetWork';
import { useRouter } from 'vue-router';
import { PageEnum } from '/@/enums/pageEnum';
import { useTimeout } from '/@/hooks/core/useTimeout';
import { ExceptionEnum } from '/@/enums/exceptionEnum';
let app: App;
export function setApp(_app: App): void {
......@@ -84,28 +79,3 @@ export function useConfigProvider() {
transformCellText,
};
}
// Initialize network monitoring
export function useListenerNetWork() {
const { listenNetWork } = appStore.getProjectConfig;
if (!listenNetWork) return;
const { replace } = useRouter();
// Check network status
useNetWork({
onLineFn: () => {
replace(PageEnum.BASE_HOME).then(() => {
useTimeout(() => {
appStore.commitPageLoadingState(false);
}, 200);
});
},
offLineFn: () => {
replace({
path: PageEnum.ERROR_PAGE,
query: {
status: String(ExceptionEnum.NET_WORK_ERROR),
},
});
},
});
}
import { isServer } from '/@/utils/is';
let lastTime = 0;
const prefixes = 'webkit moz ms o'.split(' ');
let requestAnimationFrame: typeof window.requestAnimationFrame;
let cancelAnimationFrame: typeof window.cancelAnimationFrame;
(() => {
const NO_LOOP: any = () => {};
const getWindowFrame = (name: string) => {
return name as any;
};
if (isServer) {
requestAnimationFrame = cancelAnimationFrame = NO_LOOP;
} else {
requestAnimationFrame = window.requestAnimationFrame;
cancelAnimationFrame = window.cancelAnimationFrame;
let prefix;
for (let i = 0; i < prefixes.length; i++) {
if (requestAnimationFrame && cancelAnimationFrame) {
break;
}
prefix = prefixes[i];
requestAnimationFrame =
requestAnimationFrame || window[getWindowFrame(prefix + 'RequestAnimationFrame')];
cancelAnimationFrame =
cancelAnimationFrame ||
window[getWindowFrame(prefix + 'CancelAnimationFrame')] ||
window[getWindowFrame(prefix + 'CancelRequestAnimationFrame')];
}
// If the current browser does not support requestAnimationFrame and cancelAnimationFrame, it will fall back to setTimeout
if (!requestAnimationFrame || !cancelAnimationFrame) {
requestAnimationFrame = function (callback: Fn) {
const currTime = new Date().getTime();
const timeToCall = Math.max(0, 16 - (currTime - lastTime));
const id = window.setTimeout(() => {
/* eslint-disable-next-line */
callback(currTime + timeToCall);
}, timeToCall);
lastTime = currTime + timeToCall;
return id;
};
cancelAnimationFrame = function (id: number) {
window.clearTimeout(id);
};
}
}
})();
export { requestAnimationFrame, cancelAnimationFrame };
......@@ -10,7 +10,7 @@
import { Spin } from 'ant-design-vue';
import { getViewportOffset } from '/@/utils/domUtils';
import { useWindowSizeFn } from '/@/hooks/event/useWindowSize';
import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
export default defineComponent({
name: 'IFrame',
......
......@@ -1725,6 +1725,21 @@
vscode-languageserver-textdocument "^1.0.1"
vscode-uri "^2.1.2"
"@vueuse/core@^4.0.0-beta.40":
version "4.0.0-beta.40"
resolved "https://registry.npmjs.org/@vueuse/core/-/core-4.0.0-beta.40.tgz#7efdc15c1b994647dff7ae65c0ca573d96ce9b28"
integrity sha512-FOTOUrXAAp0NOmy8hMlP1HpUhnB8LeRJZDOEUl/A9gKMDwWvPTEvxKsDAIzSa4s7I0MapVzfeP3soNCNfl9+vQ==
dependencies:
"@vueuse/shared" "4.0.0-beta.40"
vue-demi latest
"@vueuse/shared@4.0.0-beta.40":
version "4.0.0-beta.40"
resolved "https://registry.npmjs.org/@vueuse/shared/-/shared-4.0.0-beta.40.tgz#76e9b52228159e7ec88df2c8f4eea8fce1a42ec3"
integrity sha512-Ay71viUTXs0XX2hQ04kEExhpsCrw3KankBMP7euorsPjuQmIZjUA4NNOb45UAudg+uF5HXLpgWLvwb4cMOLHnQ==
dependencies:
vue-demi latest
JSONStream@^1.0.4:
version "1.3.5"
resolved "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0"
......@@ -8233,6 +8248,11 @@ vscode-uri@^2.1.2:
resolved "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.1.2.tgz#c8d40de93eb57af31f3c715dd650e2ca2c096f1c"
integrity sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==
vue-demi@latest:
version "0.4.3"
resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.4.3.tgz#6aaa9b52f02c32b4f9d4d11f02a1ae71031453c3"
integrity sha512-1DzLcZgHC9ZyFEYR4qZ83TdS1u9DglG8XVesBXqtbbmqFuO7sb8KG36kMfZCszieAweRDwAAVSAzjmEMG0+WwA==
vue-eslint-parser@^7.1.1:
version "7.1.1"
resolved "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.1.1.tgz#c43c1c715ff50778b9a7e9a4e16921185f3425d3"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册