minhuaF / blog

I will write my front-end story.
9 stars 1 forks source link

【JS基础】react 实现 防抖和节流 #18

Open minhuaF opened 3 years ago

minhuaF commented 3 years ago

这个就是说多无畏,动手实践就能理解系列

什么是防抖和节流

防抖

触发高频事件后 n秒内 函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。

节流

高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率。

防抖和节流的区别

...... 不知怎么表达系列,直接看下面代码吧

防抖和节流的实现

以下实现是基于react的,如果想看原生的话,请点击这里

防抖

我用react代码实现了一个按钮的点击事件

场景假设:用户点击按钮会发送接口请求,用户频繁点击了很多次,那这个按钮的交互要怎么处理呢?

import React from 'react';

let timer = null;

/**
 * 防抖
 * 点击按钮发送异步请求
 */
export default function Debounce() {
  const fetchData = () => {
    clearTimeout(timer);
    timer = setTimeout(() => {
      console.log('间隔1s,请求响应')
    }, 1000)
  }
  return (
    <div >
      <button onClick={fetchData}>点击发送请求</button>
    </div>
  )
}

节流

节流这个最常见的便是鼠标移动元素了 场景假设:页面上有个小公仔,鼠标移动的时候,公仔会更着移动

import React, { useState, useRef, useEffect } from 'react';
import strawberry from '../../assets/img/strawberry.png';

/**
 * 节流
 * 图标跟随图标移动
 * 实现思路:节流阀控制函数触发的机制
 */
export default function Throttle() {
  const ref = useRef(null);
  const flag = useRef(true);
  const [style, setStyle] = useState({
    left: 0,
    top: 0,
  });
  useEffect(() => {
    let timer = null;
    document.addEventListener('mousemove', (e) => {
      if(flag.current) {
        if(!flag.current) return;
        flag.current = false;
        timer = setTimeout(() => {
          console.log('strawberry move')
          setStyle({
            left: e.pageX,
            top: e.pageY
          })
          flag.current = true;
        }, 50)
      }
    })
    return () => clearTimeout(timer);
  }, [])
  return (
    <div>
      <img
        style={{
          position: 'absolute',
          ...style
        }}
        src={strawberry}
        alt="strawberry"
        ref={ref}
      />
    </div>
  )
}

总结

对于防抖和节流,掌握的最好方式就是根据实际场景去解决问题,对比效果之后就能掌握它们的概念和区别,那么在后面的编程中,也能熟悉应用。

参考资料

第 3 题:什么是防抖和节流?有什么区别?如何实现?