防抖debounce

防抖过程

当事件触发时,响应的函数不会立即出发,而是等待一定时间

当事件密集触发时,函数的触发就会频繁的推迟

只有等待了一段时间也没有事件触发,才会真正执行响应函数

应用场景

  • 输入框中输入内容,搜索或者提交信息
  • 频繁的点击按钮
  • 监听浏览器的滚动事件
  • 用户缩放浏览器的resize事件

实现方法

1.第三方库(lodash,underscore)

2.手写实现(立即控制+取消功能)

  1. function debounce(fn,delay,immediate=false){
  2. // 记录定时器
  3. let timer=null;
  4. // 记录当前执行状态
  5. let isInvoke=false;
  6. const _debounce= function(...args){
  7. // 清除上一次定时器
  8. if(timer) clearTimeout(timer);
  9. if(!isInvoke&&immediate){
  10. // 开始立即实行
  11. fn.apply(this,args);
  12. isInvoke=true;
  13. }else{
  14. // 延迟执行
  15. timer=setTimeout(()=>{
  16. fn.apply(this,args);
  17. isInvoke=false;
  18. timer=null;
  19. },delay);
  20. }
  21. };
  22. // 取消抖动功能
  23. _debounce.cancel=function(){
  24. if(timer) clearTimeout(timer);
  25. isInvoke=false;
  26. timer=null;
  27. }
  28. return _debounce;
  29. }

节流throttle

节流过程

当事件触发时,会执行这个事件的响应函数

如果这个事件被频繁触发,那么节流函数会按照一定的频率来执行函数

不管在这个中间有多少次触发,执行函数的频率总是固定的

应用场景

  • 监听页面的滚动事件

  • 鼠标的移动事件

  • 用户频繁点 击按钮操作

实现方式

1.利用定时器手动实现

  1. function throttle(fn,interval){
  2. let isInvoke=false;
  3. function _throttle(...args){
  4. if(!isInvoke){
  5. isInvoke=true;
  6. fn.apply(this,args);
  7. setTimeout(()=>{
  8. isInvoke=false;
  9. },interval);
  10. }
  11. }
  12. return _throttle;
  13. }

2.利用时间戳手动实现(前置、后置控制+取消功能)

  1. function throttle(fn,interval,option={leading:true,trailing:false}){
  2. let lastTime=0;
  3. let timer=null;
  4. const {leading,trailing}=option;
  5. function _throttle(...args){
  6. const nowTime=new Date().getTime();
  7. // 取消首次触发
  8. if(!leading && lastTime===0){
  9. lastTime=nowTime;
  10. }
  11. const remainTime=interval-(nowTime-lastTime);
  12. if(remainTime<=0){
  13. // 正常执行
  14. if(timer){
  15. clearTimeout(timer);
  16. timer=null;
  17. }
  18. fn.apply(this,args);
  19. lastTime=nowTime;
  20. }else if(trailing && !timer){
  21. // 开启后续触发
  22. timer=setTimeout(()=>{
  23. fn.apply(this,args);
  24. lastTime=!leading ? 0 : new Date().getTime();
  25. timer=null;
  26. },remainTime)
  27. }
  28. }
  29. // 取消后续触发功能
  30. _throttle.cancel=()=>{
  31. if(timer) clearTimeout(timer);
  32. timer=null;
  33. lastTime=0;
  34. }
  35. return _throttle;
  36. }