debounce 去抖
更新时间:2023-02-22 15:57:53标签:web前端
常见的防抖实现
1import { useMemo, useRef } from 'react';23export function debounce<T extends (...args: any[]) => any>(fn: T, delay: number) {4 let timer: number;5 const cancel = () => {6 window.clearTimeout(timer);7 };8 const callback = (...args: any[]) => {9 cancel();10 timer = window.setTimeout(() => {11 fn(...args);12 }, delay);13 };14 return [callback, cancel];15}1617export const useDebounce = <T extends (...args: any[]) => any>(fn: T, delay = 500) => {18 const ref = useRef<T>();19 ref.current = fn;20 return useMemo(() => {21 return debounce((...args: any[]) => {22 ref.current?.(...args);23 }, delay);24 }, [delay]) as [T, () => void];25};
应用
results:
代码
1import { ChangeEvent, FC, useState } from 'react';2import { useDebounce } from '@shared/utils';34export const DebounceExample: FC = () => {56 const [result, setResult] = useState('');7 const [handleChange] = useDebounce((e: ChangeEvent<HTMLInputElement>) => {8 setResult(e.target.value);9 }, 500);1011 return (12 <div>13 <input onChange={handleChange} type="text"/>14 <p>results: { result }</p>15 </div>16 );17};
其他
1import { DependencyList, useMemo } from 'react';23interface FNFactory<T>{4 (callback: (post: () => any) => void): T;5}6export function trailed<T extends (...args: any[]) => any>(fn: FNFactory<T>): T {7 let count = 0;8 const callback = (post: () => any) => {9 count += 1;10 Promise.resolve().then(() => {11 if (count > 1) return count -= 1;12 count = 0;13 post();14 });15 };16 return fn(callback);17}1819export const useTrailed = <T extends (...args: any[]) => any>(fn: FNFactory<T>, deps: DependencyList) => {20 // eslint-disable-next-line react-hooks/exhaustive-deps21 return useMemo(() => trailed(fn), deps);22};
示例
代码
1import { FC, useCallback } from 'react';2import { useTrailed } from '@shared/utils';3import styled from 'styled-components';45const Wrapper = styled.div`6 margin: 0 0 20px 0;7 & > *:not(:first-child) {8 margin-left: 10px;9 }10`;11export const TrailedExample: FC = () => {1213 const counting = useTrailed((callback) => {14 return (num: number) => {15 // eslint-disable-next-line no-console16 console.log(num);17 callback(() => {18 // eslint-disable-next-line no-console19 console.log('Complete!');20 });21 };22 }, []);2324 const count = useCallback((len: number) => {25 for (let i = 1; i <= len; i += 1) {26 counting(i);27 }28 }, [counting]);2930 return (31 <Wrapper>32 <button onClick={() => count(5)}>5次打印</button>33 <button onClick={() => count(10)}>10次打印</button>34 </Wrapper>35 );36};