结合开发场景理解防抖与节流

204 阅读2分钟

**防抖(debounce)和节流(throttle)是两种常用的优化高频触发事件的方法。**钙片文章主要是搞清楚防抖与节流函数的代码逻辑,讲解他们在真实项目中的运用与实践

防抖:当持续触发事件时,一定时间段内没有再触发事件,函数才会执行一次,如果在这个时间段内又触发了事件,则会重新开始延时。常用于输入框搜索、滚动加载等场景。

节流:当持续触发事件时,保证一定时间段内只触发一次事件处理函数。常用于滚动监听、窗口大小改变等场景。

防抖debounce

剖析防抖函数的特点 在一段时间内执行多次,但是只有最后一次执行生效

//简化版防抖函数
function debounce(callBack,delay){
     let timer = null
	clearTimeout(timer)
     timer = setTimeout(callBack,delay)
}

这里完成了基本的防抖操作,接下来进阶版本

fucntion debounce(callBack,delay){
  let timer = null;
    return function (){
		const context = this
		const args = arguments
		clearTimeout(timer)
		timer = setTimeout(()=>{
			callBack.aplly(context,args)
		})
    }
}

应用场景实列

1.模糊查询:我们在实际开发中可能会遇到当用户在搜索框中输入时,搜索框下面会出现一片区域,用来展示你通过输入的关键字查询到的一些结果,此时你并不希望一输入内容就开始查询,而是等你输入完成需要查询的内容再去查询

import { onMounted } from "vue";

const inputHandler = (e: Event) => {
  console.log((e.target as HTMLInputElement).value);
};

const debounce = <T extends (...args: any[]) => void>(
  callBack: T,
  delay: number
): ((...args: Parameters<T>) => void) => {
  let timer: number | null = null;
  return (...args: Parameters<T>) => {
    if (timer !== null) {
      clearTimeout(timer);
    }
    timer = window.setTimeout(() => callBack(...args), delay);
  };
};
onMounted(() => {
  const input = document.getElementById("debouncedInput");

  // 将回调函数包装在防抖函数中,设置防抖延迟时间为 300 毫秒
  const debouncedHandleInput = debounce(inputHandler, 300);

  // 给输入框添加 input 事件监听器
  input?.addEventListener("input", debouncedHandleInput);
});

这里能有效优化请求效率

防抖 throttle

通俗来说就是我在一段时间内,按照一定的频率来执行事件,主要是对一些高触发频率的事件结合使用

const throttle = (callBack,delay)=>{
  let lastTime = 0 ;
  return (...args)=>{
    let now = Date.now();
    if(now-lastTime>delay){
      callBack(args)
      lastTime = now
    }
  }
}

1.场景滚动事件触发

const throttle = <T extends (...args: any[]) => void>(
  callBack: T,
  delay: number
): ((...args: Parameters<T>) => void) => {
  let lastTime = 0;
  return (...args: Parameters<T>) => {
    let now = Date.now();
    if (now - lastTime > delay) {
      callBack(...args);
      lastTime = now;
    }
  };
};

onMounted(() => {
  const box = document.getElementById("box");
//限制触发频率为间隔500ms触发一下滚动事件
  const throttleHandleScroll = throttle(scrollHandler, 500);

  box?.addEventListener("scroll", throttleHandleScroll);
});

 <div id="box">
    <p>1</p>
    <p>1</p>
    <p>1</p>
    <p>1</p>
    <p>1</p>
    <p>1</p>
    <p>1</p>
    <p>1</p>
    <p>1</p>
    <p>1</p>
    <p>1</p>
  </div>

#box {
  height: 200px;
  width: 200px;
  overflow: auto;
  border: 1px solid #000;
}

#box p {
  height: 100px;
  margin: 0;
  padding: 0;
}

还有鼠标移动事件,mousemove,表单提交频率

//场景二 表单提交按钮
const submitButtonFetch =async()=>{ const result = awiat fetch('./userForm')}
const debounceSubMit = throttle(submitButtonFetch, 500)
btn.addEventListener('click', debounceSubMit)

//其实和添加loading效果一样每间隔一个loading动画时间才能继续提交请求

感谢!!!!