1. 基本概念--是什么?
原理: 一个 dom 事件被触发时,会设定一个延迟处理时间,事件在这个时间中再次触发则被视为无效!简单来说,对多次触发事件的函数,在规定时间内,只执行一次 。
2. 需求描述--有啥用?
场景
鼠标在某个盒子内移动时需要鼠标的坐标
问题
当鼠标在移动时,mosemove事件会被一直触发,浪费了浏览器的性能!
3. 需求分析--分析问题!
我们需要一个工具函数(或者hooks),这个工具函数(或者hooks)需要有以下几个功能:
参数 | 含义 | 默认值 |
---|---|---|
value | 需要节流的值 | - |
wait | 时间周期,单位为毫秒 | 500 |
综上所述,梳理思路如下:
首先
声明一个函数(或hooks)useThrottle 。此函数接受需要防抖的值和自定义时间周期。
其次
使用定时器完成之间模拟时间周期。当事件触发后,如果之前的定时器存在则无视此事件;否则声明一个定时器。
最后
声明响应式数据 throttleValue,将节流的值赋值给声明的响应式数据并将其作为该函数(或hooks)的返回值。
4. 手动实现--独立自主!
jsx
function useThrottle(...props) {
let [value, { wait = 500 }] = props
// 定时器,useRef无论组件渲染多少次,useRef始终如一
const throttleTime = useRef(null)
// 节流的值
const throttleValue = useRef(null)
// 如果定时器不存在
if (!throttleTime.current) {
// 开辟定时器
throttleTime.current = setTimeout(() => {
// 将原有的定时器清掉
throttleTime.current = null
// 设置节流新值
throttleValue.current = value
}, wait);
}
return throttleValue.current
}
// 测试
export default () => {
let [x, setX] = useState(0)
function onMouseMove({ pageX }) {
setX(pageX)
}
const throttleValue = useThrottle(x, { wait: 500 });
return <><div
style={{ width: "300px", height: "300px", backgroundColor: 'pink' }}
onMouseMove={onMouseMove}>
</div>
<h1> {throttleValue}</h1>
</>
}