refactor: raf

doc-form
tangjinzhou 2021-12-19 11:06:55 +08:00
parent b77ca0eed7
commit 257f7f03b5
16 changed files with 63 additions and 63 deletions

View File

@ -14,8 +14,7 @@ import {
} from 'vue'; } from 'vue';
import canUseDom from './canUseDom'; import canUseDom from './canUseDom';
import ScrollLocker from '../vc-util/Dom/scrollLocker'; import ScrollLocker from '../vc-util/Dom/scrollLocker';
import type { RafFrame } from './raf'; import raf from './raf';
import wrapperRaf from './raf';
let openCount = 0; let openCount = 0;
const supportDom = canUseDom(); const supportDom = canUseDom();
@ -62,7 +61,7 @@ export default defineComponent({
setup(props, { slots }) { setup(props, { slots }) {
const container = ref<HTMLElement>(); const container = ref<HTMLElement>();
const componentRef = ref(); const componentRef = ref();
const rafId = ref<RafFrame>(); const rafId = ref<number>();
const scrollLocker = new ScrollLocker({ const scrollLocker = new ScrollLocker({
container: getParent(props.getContainer) as HTMLElement, container: getParent(props.getContainer) as HTMLElement,
}); });
@ -176,7 +175,7 @@ export default defineComponent({
nextTick(() => { nextTick(() => {
if (!attachToParent()) { if (!attachToParent()) {
rafId.value = wrapperRaf(() => { rafId.value = raf(() => {
instance.update(); instance.update();
}); });
} }
@ -190,7 +189,7 @@ export default defineComponent({
openCount = visible && openCount ? openCount - 1 : openCount; openCount = visible && openCount ? openCount - 1 : openCount;
} }
removeCurrentContainer(); removeCurrentContainer();
wrapperRaf.cancel(rafId.value); raf.cancel(rafId.value);
}); });
return () => { return () => {

View File

@ -1,6 +1,6 @@
import type { Ref } from 'vue'; import type { Ref } from 'vue';
import { onBeforeUnmount, ref } from 'vue'; import { onBeforeUnmount, ref } from 'vue';
import wrapperRaf from '../raf'; import raf from '../raf';
export type Updater<State> = (prev: State) => State; export type Updater<State> = (prev: State) => State;
/** /**
@ -15,10 +15,10 @@ export function useLayoutState<State>(
let updateBatchRef = []; let updateBatchRef = [];
const rafRef = ref(); const rafRef = ref();
function setFrameState(updater: Updater<State>) { function setFrameState(updater: Updater<State>) {
wrapperRaf.cancel(rafRef.value); raf.cancel(rafRef.value);
updateBatchRef.push(updater); updateBatchRef.push(updater);
rafRef.value = wrapperRaf(() => { rafRef.value = raf(() => {
const prevBatch = updateBatchRef; const prevBatch = updateBatchRef;
// const prevState = stateRef.value; // const prevState = stateRef.value;
updateBatchRef = []; updateBatchRef = [];
@ -34,7 +34,7 @@ export function useLayoutState<State>(
} }
onBeforeUnmount(() => { onBeforeUnmount(() => {
wrapperRaf.cancel(rafRef.value); raf.cancel(rafRef.value);
}); });
return [stateRef as Ref<State>, setFrameState]; return [stateRef as Ref<State>, setFrameState];

View File

@ -1,33 +1,47 @@
import getRequestAnimationFrame, { cancelRequestAnimationFrame } from './getRequestAnimationFrame'; let raf = (callback: FrameRequestCallback) => +setTimeout(callback, 16);
let caf = (num: number) => clearTimeout(num);
const oriRaf = getRequestAnimationFrame(); if (typeof window !== 'undefined' && 'requestAnimationFrame' in window) {
raf = (callback: FrameRequestCallback) => window.requestAnimationFrame(callback);
caf = (handle: number) => window.cancelAnimationFrame(handle);
}
export type RafFrame = { let rafUUID = 0;
id: number; const rafIds = new Map<number, number>();
};
// Support call raf with delay specified frame
export default function raf(callback: () => void, delayFrames = 1): { id: number } {
let restFrames: number = delayFrames;
function internalCallback() { function cleanup(id: number) {
restFrames -= 1; rafIds.delete(id);
}
if (restFrames <= 0) { export default function wrapperRaf(callback: () => void, times = 1): number {
rafUUID += 1;
const id = rafUUID;
function callRef(leftTimes: number) {
if (leftTimes === 0) {
// Clean up
cleanup(id);
// Trigger
callback(); callback();
} else { } else {
frame.id = oriRaf(internalCallback); // Next raf
const realId = raf(() => {
callRef(leftTimes - 1);
});
// Bind real raf id
rafIds.set(id, realId);
} }
} }
const frame = { callRef(times);
id: oriRaf(internalCallback),
};
return frame; return id;
} }
raf.cancel = function cancel(frame?: { id: number }) { wrapperRaf.cancel = (id: number) => {
if (!frame) return; const realId = rafIds.get(id);
cleanup(realId);
cancelRequestAnimationFrame(frame.id); return caf(realId);
}; };

View File

@ -1,8 +1,7 @@
import type { RafFrame } from './raf';
import raf from './raf'; import raf from './raf';
export default function throttleByAnimationFrame(fn: (...args: any[]) => void) { export default function throttleByAnimationFrame(fn: (...args: any[]) => void) {
let requestId: RafFrame; let requestId: number;
const later = (args: any[]) => () => { const later = (args: any[]) => () => {
requestId = null; requestId = null;

View File

@ -4,7 +4,6 @@ import { computed, defineComponent, onBeforeUnmount, ref, watch } from 'vue';
import type { MenuMode } from './interface'; import type { MenuMode } from './interface';
import { useInjectForceRender, useInjectMenu } from './hooks/useMenuContext'; import { useInjectForceRender, useInjectMenu } from './hooks/useMenuContext';
import { placements, placementsRtl } from './placements'; import { placements, placementsRtl } from './placements';
import type { RafFrame } from '../../_util/raf';
import raf from '../../_util/raf'; import raf from '../../_util/raf';
import classNames from '../../_util/classNames'; import classNames from '../../_util/classNames';
import { getTransitionProps } from '../../_util/transition'; import { getTransitionProps } from '../../_util/transition';
@ -54,7 +53,7 @@ export default defineComponent({
const popupPlacement = computed(() => popupPlacementMap[props.mode]); const popupPlacement = computed(() => popupPlacementMap[props.mode]);
const visibleRef = ref<RafFrame>(); const visibleRef = ref<number>();
watch( watch(
() => props.visible, () => props.visible,
visible => { visible => {

View File

@ -1,6 +1,5 @@
import { onBeforeUnmount, watch, onActivated, defineComponent, ref } from 'vue'; import { onBeforeUnmount, watch, onActivated, defineComponent, ref } from 'vue';
import Tooltip, { tooltipProps } from '../tooltip'; import Tooltip, { tooltipProps } from '../tooltip';
import type { RafFrame } from '../_util/raf';
import raf from '../_util/raf'; import raf from '../_util/raf';
export default defineComponent({ export default defineComponent({
@ -10,7 +9,7 @@ export default defineComponent({
setup(props, { attrs, slots }) { setup(props, { attrs, slots }) {
const innerRef = ref<any>(null); const innerRef = ref<any>(null);
const rafRef = ref<RafFrame>(null); const rafRef = ref<number>(null);
function cancelKeepAlign() { function cancelKeepAlign() {
raf.cancel(rafRef.value!); raf.cancel(rafRef.value!);

View File

@ -22,8 +22,7 @@ import { onBeforeUnmount, defineComponent, ref, watch, watchEffect, computed } f
import PropTypes from '../../../_util/vue-types'; import PropTypes from '../../../_util/vue-types';
import useSyncState from '../hooks/useSyncState'; import useSyncState from '../hooks/useSyncState';
import useState from '../../../_util/hooks/useState'; import useState from '../../../_util/hooks/useState';
import type { RafFrame } from '../../../_util/raf'; import raf from '../../../_util/raf';
import wrapperRaf from '../../../_util/raf';
import classNames from '../../../_util/classNames'; import classNames from '../../../_util/classNames';
import ResizeObserver from '../../../vc-resize-observer'; import ResizeObserver from '../../../vc-resize-observer';
import { toPx } from '../../../_util/util'; import { toPx } from '../../../_util/util';
@ -340,9 +339,9 @@ export default defineComponent({
const activeTabOffset = computed(() => tabOffsets.value.get(props.activeKey)); const activeTabOffset = computed(() => tabOffsets.value.get(props.activeKey));
// Delay set ink style to avoid remove tab blink // Delay set ink style to avoid remove tab blink
const inkBarRafRef = ref<RafFrame>(); const inkBarRafRef = ref<number>();
const cleanInkBarRaf = () => { const cleanInkBarRaf = () => {
wrapperRaf.cancel(inkBarRafRef.value); raf.cancel(inkBarRafRef.value);
}; };
watch([activeTabOffset, tabPositionTopOrBottom, () => props.rtl], () => { watch([activeTabOffset, tabPositionTopOrBottom, () => props.rtl], () => {
@ -364,7 +363,7 @@ export default defineComponent({
} }
cleanInkBarRaf(); cleanInkBarRaf();
inkBarRafRef.value = wrapperRaf(() => { inkBarRafRef.value = raf(() => {
setInkStyle(newInkStyle); setInkStyle(newInkStyle);
}); });
}); });

View File

@ -1,16 +1,15 @@
import type { Ref } from 'vue'; import type { Ref } from 'vue';
import { ref, onBeforeUnmount } from 'vue'; import { ref, onBeforeUnmount } from 'vue';
import type { RafFrame } from '../../../_util/raf'; import raf from '../../../_util/raf';
import wrapperRaf from '../../../_util/raf';
export default function useRaf<Callback extends Function>(callback: Callback) { export default function useRaf<Callback extends Function>(callback: Callback) {
const rafRef = ref<RafFrame>(); const rafRef = ref<number>();
const removedRef = ref(false); const removedRef = ref(false);
function trigger(...args: any[]) { function trigger(...args: any[]) {
if (!removedRef.value) { if (!removedRef.value) {
wrapperRaf.cancel(rafRef.value); raf.cancel(rafRef.value);
rafRef.value = wrapperRaf(() => { rafRef.value = raf(() => {
callback(...args); callback(...args);
}); });
} }
@ -18,7 +17,7 @@ export default function useRaf<Callback extends Function>(callback: Callback) {
onBeforeUnmount(() => { onBeforeUnmount(() => {
removedRef.value = true; removedRef.value = true;
wrapperRaf.cancel(rafRef.value); raf.cancel(rafRef.value);
}); });
return trigger; return trigger;

View File

@ -1,4 +1,3 @@
import type { RafFrame } from '../../../_util/raf';
import raf from '../../../_util/raf'; import raf from '../../../_util/raf';
import { onMounted, reactive, ref } from 'vue'; import { onMounted, reactive, ref } from 'vue';
@ -6,7 +5,7 @@ type SetActionType<T> = Partial<T> | ((state: T) => Partial<T>);
export default function useFrameSetState<T extends object>( export default function useFrameSetState<T extends object>(
initial: T, initial: T,
): [Record<string, any>, (newState: SetActionType<T>) => void] { ): [Record<string, any>, (newState: SetActionType<T>) => void] {
const frame = ref<RafFrame>(null); const frame = ref<number>(null);
const state = reactive({ ...initial }); const state = reactive({ ...initial });
const queue = ref<SetActionType<T>[]>([]); const queue = ref<SetActionType<T>[]>([]);

View File

@ -1,4 +1,3 @@
import type { RafFrame } from '../../_util/raf';
import raf from '../../_util/raf'; import raf from '../../_util/raf';
import type { ComputedRef, Ref, UnwrapRef } from 'vue'; import type { ComputedRef, Ref, UnwrapRef } from 'vue';
import { ref, onBeforeUnmount, watch } from 'vue'; import { ref, onBeforeUnmount, watch } from 'vue';
@ -10,7 +9,7 @@ export default function useHoverValue<DateType>(
{ formatList, generateConfig, locale }: ValueTextConfig<DateType>, { formatList, generateConfig, locale }: ValueTextConfig<DateType>,
): [ComputedRef<string>, (date: DateType) => void, (immediately?: boolean) => void] { ): [ComputedRef<string>, (date: DateType) => void, (immediately?: boolean) => void] {
const innerValue = ref<DateType>(null); const innerValue = ref<DateType>(null);
let rafId: RafFrame; let rafId: number;
function setValue(val: DateType, immediately = false) { function setValue(val: DateType, immediately = false) {
raf.cancel(rafId); raf.cancel(rafId);

View File

@ -1,15 +1,14 @@
import isVisible from '../../vc-util/Dom/isVisible'; import isVisible from '../../vc-util/Dom/isVisible';
import KeyCode from '../../_util/KeyCode'; import KeyCode from '../../_util/KeyCode';
import type { RafFrame } from '../../_util/raf';
import raf from '../../_util/raf'; import raf from '../../_util/raf';
import type { GenerateConfig } from '../generate'; import type { GenerateConfig } from '../generate';
import type { CustomFormat, PanelMode, PickerMode } from '../interface'; import type { CustomFormat, PanelMode, PickerMode } from '../interface';
const scrollIds = new Map<HTMLElement, RafFrame>(); const scrollIds = new Map<HTMLElement, number>();
/** Trigger when element is visible in view */ /** Trigger when element is visible in view */
export function waitElementReady(element: HTMLElement, callback: () => void): () => void { export function waitElementReady(element: HTMLElement, callback: () => void): () => void {
let id: RafFrame; let id: number;
function tryOrNextFrame() { function tryOrNextFrame() {
if (isVisible(element)) { if (isVisible(element)) {

View File

@ -1,6 +1,5 @@
import addEventListenerWrap from '../../vc-util/Dom/addEventListener'; import addEventListenerWrap from '../../vc-util/Dom/addEventListener';
import type { EventHandler } from '../../_util/EventInterface'; import type { EventHandler } from '../../_util/EventInterface';
import type { RafFrame } from '../../_util/raf';
import raf from '../../_util/raf'; import raf from '../../_util/raf';
import { defineComponent, onUnmounted, computed, ref, watchEffect, getCurrentInstance } from 'vue'; import { defineComponent, onUnmounted, computed, ref, watchEffect, getCurrentInstance } from 'vue';
import type { PropType } from 'vue'; import type { PropType } from 'vue';
@ -74,7 +73,7 @@ export default defineComponent({
const instance = getCurrentInstance(); const instance = getCurrentInstance();
let baseWidth = 0; let baseWidth = 0;
const dragging = ref(false); const dragging = ref(false);
let rafId: RafFrame; let rafId: number;
const updateWidth = (e: HandleEvent) => { const updateWidth = (e: HandleEvent) => {
let pageX = 0; let pageX = 0;
if (e.touches) { if (e.touches) {

View File

@ -1,4 +1,3 @@
import type { RafFrame } from '../../_util/raf';
import raf from '../../_util/raf'; import raf from '../../_util/raf';
import type { Ref, UnwrapRef } from 'vue'; import type { Ref, UnwrapRef } from 'vue';
import { onBeforeUnmount, ref, shallowRef } from 'vue'; import { onBeforeUnmount, ref, shallowRef } from 'vue';
@ -9,7 +8,7 @@ export function useLayoutState<State>(
defaultState: State, defaultState: State,
): [Ref<State>, (updater: Updater<State>) => void] { ): [Ref<State>, (updater: Updater<State>) => void] {
const stateRef = shallowRef<State>(defaultState); const stateRef = shallowRef<State>(defaultState);
let rafId: RafFrame; let rafId: number;
const updateBatchRef = shallowRef<Updater<State>[]>([]); const updateBatchRef = shallowRef<Updater<State>[]>([]);
function setFrameState(updater: Updater<State>) { function setFrameState(updater: Updater<State>) {
updateBatchRef.value.push(updater); updateBatchRef.value.push(updater);

View File

@ -1,6 +1,5 @@
import type { Ref } from 'vue'; import type { Ref } from 'vue';
import { onBeforeUnmount, ref, watch, onMounted } from 'vue'; import { onBeforeUnmount, ref, watch, onMounted } from 'vue';
import type { RafFrame } from '../../_util/raf';
import raf from '../../_util/raf'; import raf from '../../_util/raf';
/** /**
@ -24,7 +23,7 @@ export default (
doMeasure: Func, doMeasure: Func,
): [Ref<PopupStatus>, (callback?: () => void) => void] => { ): [Ref<PopupStatus>, (callback?: () => void) => void] => {
const status = ref<PopupStatus>(null); const status = ref<PopupStatus>(null);
const rafRef = ref<RafFrame>(); const rafRef = ref<number>();
const destroyRef = ref(false); const destroyRef = ref(false);
function setStatus(nextStatus: PopupStatus) { function setStatus(nextStatus: PopupStatus) {
if (!destroyRef.value) { if (!destroyRef.value) {

View File

@ -1,5 +1,4 @@
import type { Ref } from 'vue'; import type { Ref } from 'vue';
import type { RafFrame } from '../../_util/raf';
import raf from '../../_util/raf'; import raf from '../../_util/raf';
import isFF from '../utils/isFirefox'; import isFF from '../utils/isFirefox';
import useOriginScroll from './useOriginScroll'; import useOriginScroll from './useOriginScroll';
@ -16,7 +15,7 @@ export default function useFrameWheel(
onWheelDelta: (offset: number) => void, onWheelDelta: (offset: number) => void,
): [(e: WheelEvent) => void, (e: FireFoxDOMMouseScrollEvent) => void] { ): [(e: WheelEvent) => void, (e: FireFoxDOMMouseScrollEvent) => void] {
let offsetRef = 0; let offsetRef = 0;
let nextFrame: RafFrame = null; let nextFrame: number = null;
// Firefox patch // Firefox patch
let wheelValue = null; let wheelValue = null;

View File

@ -1,6 +1,5 @@
import type { Data } from '../../_util/type'; import type { Data } from '../../_util/type';
import type { ComputedRef, Ref } from 'vue'; import type { ComputedRef, Ref } from 'vue';
import type { RafFrame } from '../../_util/raf';
import raf from '../../_util/raf'; import raf from '../../_util/raf';
import type { GetKey } from '../interface'; import type { GetKey } from '../interface';
@ -14,7 +13,7 @@ export default function useScrollTo(
syncScrollTop: (newTop: number) => void, syncScrollTop: (newTop: number) => void,
triggerFlash: () => void, triggerFlash: () => void,
) { ) {
let scroll: RafFrame = null; let scroll: number;
return (arg?: any) => { return (arg?: any) => {
// When not argument provided, we think dev may want to show the scrollbar // When not argument provided, we think dev may want to show the scrollbar