项目踩坑1-节流与防抖
项目:基于vue的专业课程系统
遇到问题: 下拉显示更多的电影,实现一个鼠标拖拽Y轴到底部显示一个返回首页的游标的组件时资源加载慢页面卡顿
节流与防抖是什么
是优化高频率执行代码的一种手段:如window对象频繁的onresize onscroll keypress mousemove 等事件在出发时, 会不断地调用绑定在事件上的回调函数,浪费资源,利用节流与防抖减少调用
定义
节流(throttle ): n秒内只执行一次,若在n秒内重复触发,只有一次生效
防抖(debounce):n秒后再执行该事件,若在n秒内被重复触发, 则重新记时
假设电梯有两种运行策略 debounce 和 throttle,超时设定为15秒,不考虑容量限制
电梯第一个人进来后,15秒后准时运送一次,这是节流
电梯第一个人进来后,等待15秒。如果过程中又有人进来,15秒等待重新计时,直到 15秒后开始运送,这是防抖
节流
时间戳,事件会立即执行,停止触发后没有办法再次执行
function throttle(func, delay = 500) { let oldtime = Date.now() return function (...args) { let newtime = Date.now() if(newtime- oldtime >= delay) { func.apply(null, args) oldtime = Date.now() } } }
func.apply(thisArg, [argsArray])
参数
返回值
调用有指定this值和参数的函数的结果。
定时器写法
function throttle(func, delay = 500) { let timer = null; return function (...args) { if(!timer) { timer = setTimeout(() => { func.apply(this, args) timer = null }, delay) } } } // dealy毫秒后第一次执行, 第二次事件停止触发后依然会再一次执行
精确写法
function throttle(func, delay) { let timer = null; let startTime = Date.now() //触发时时间 return function () { let currentTime = Date.now(); //当前时间 let remaining = delay -(currentTime - startTime); let context = this; let args = arguments; clearTimeout(timer) if(remaining <= 0) { func.apply(context, args) startTime = Date.now() }else{ timer = setTimeout(func, remaining); // 时间戳版的函数触发是在时间段内开始的时候,而定时器版的函数触发是在时间段内结束的时候。 } } }
防抖
function debounce(func, wait) { let timeout; return function () { let context = this; //保存this指向 let args = arguments; //拿到event对象 clearTimeout(timeout) timeout = setTimeout(function() { func.apply(context, args) }, wait) } }
立即执行,加入第三参数用于判断
function debounce(func, wait, immediate) { let timeout; return function () { let context = this; //保存this指向 let args = arguments; //拿到event对象 if(timeout) clearTimeout(timeout) //timeout 不为null if(immediate) { let callNow = !timeout; //第一次会立即执行,以后只有时间执行后才会再次触发 timeout = setTimeout(function() { timeout = null }, wait) if(callNow) { func.apply(context, args) } } else { timeout = setTimeout(function () { func.apply(context, args) }, wait); } } }
防抖在连续的事件,只需触发一次回调的场景有:
- 搜索框搜索输入。只需用户最后一次输入完,再发送请求
- 手机号、邮箱验证输入检测
- 窗口大小
resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。
节流在间隔一段时间执行一次回调的场景有:
- 滚动加载,加载更多或滚到底部监听
- 搜索框,搜索联想功能

浙公网安备 33010602011771号