【vue react 项目常用hooks】useDebounceVal
我们经常需要对搜索进行防抖,有时还需要拿到防抖后的数据传递给下游组件,这个时候就需要用到这个 useDebounceVal
,请看 vue
和 react
中分别如何实现。
1、分析
useDebounceVal
的输入是为防抖前的 val
, 还有防抖duration
,输出是一个防抖后的val
.
所以函数是长这样:
ts
declare function useDebounceVal<T>(val: T, duration: number): T;
debounce
可以自己实现,也可以使用lodash
等工具。需要注意的是,
react
中需要实现debounce
的cancel
函数,vue
可以不需要。
2、react 版
js
import { useState, useEffect } from 'react';
import { debounce } from 'lodash-es';
export function useDebounceVal(value, delay = 500) {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const handler = debounce(() => {
setDebouncedValue(value);
}, delay);
handler();
return () => handler.cancel();
}, [value, delay]);
return debouncedValue;
}
使用方法:
js
const [searchQuery, setSearchQuery] = useState('');
const debouncedSearchQuery = useDebounceVal(searchQuery);
3、vue 版
vue 版有2种,一种跟上面类似(普通版),还有一种是借助 customRef
来实现。分别如下:
3-1、普通版
js
import { ref, watch } from 'vue';
import { debounce } from 'lodash-es';
export function useDebounceVal(value, delay = 500) {
const debouncedValue = ref(value.value);
const updateValue = debounce((newValue) => {
debouncedValue.value = newValue;
}, delay);
watch(value, (newValue) => {
updateValue(newValue);
});
return debouncedValue;
}
使用方法:
js
const searchQuery = ref('');
const debouncedSearchQuery = useDebounceVal(searchQuery);
3-2、customRef版
js
import { customRef } from 'vue';
export function useDebounceRef(value, delay = 500) {
let timeout;
return customRef((track, trigger) => {
return {
get() {
track();
return value;
},
set(newValue) {
clearTimeout(timeout);
timeout = setTimeout(() => {
value = newValue;
trigger();
}, delay);
},
};
});
}
使用方法:
js
const searchQuery = useDebounceRef('');
4、分析2
看到这里有些同学可能还在疑惑,为啥要这个东西,不用可不可以。那我们先看看下面的情况。通常我们会把输入框和查询结果放到一起处理,如下:
jsx
<div className='search-container'>
<input
type='text'
value={searchQuery}
onChange={handleInputChange}
placeholder='请输入搜索内容'
/>
<SearchResults searchQuery={debouncedSearchQuery} />
</div>
但有的时候,SearchResults
逻辑不是我们控制的(比如其他同事或者下游业务),或者是我们控制但是想把逻辑内聚到 SearchResults
组件里面。期望的效果是:我们只需要把 debouncedVal
数据传递给 SearchResults
就行了,于是就有了这个 hooks
的用武之地。
diff
<div className='search-container'>
<input
type='text'
value={searchQuery}
onChange={handleInputChange}
placeholder='请输入搜索内容'
/>
- <SearchResults searchQuery={debouncedSearchQuery} />
+ <SearchResults searchVal={debouncedSearchVal} />
</div>
5、总结
本文分析了为啥需要 useDebounceVal
,并编写了 vue
和 react
版的 useDebounceVal
,有需要的自行取用。
全文完~~