什么是防抖和节流,以及如何编码实现。
本质上是优化高频率执行代码的一种手段
如:浏览器的 resize
、scroll
、keypress
、mousemove
等事件在触发时,会不断地调用绑定在事件上的回调函数,极大地浪费资源,降低前端性能
为了优化体验,需要对这类事件进行调用次数的限制,对此我们就可以采用throttle
(节流)和debounce
(防抖)的方式来减少调用频率
一、定义:
- 节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
- 防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时
二、一个经典的比喻:
想象每天上班大厦底下的电梯。把电梯完成一次运送,类比为一次函数的执行和响应
假设电梯有两种运行策略 debounce
和 throttle
,超时设定为15秒,不考虑容量限制
电梯第一个人进来后,15秒后准时运送一次,这是节流
电梯第一个人进来后,等待15秒。如果过程中又有人进来,15秒等待重新计时,直到15秒后开始运送,这是防抖
三、js代码实现:
节流
1 function throttled(fn, delay = 500) { 2 let timer = null 3 let starttime = Date.now() 4 return function () { 5 let curTime = Date.now() // 当前时间 6 let remaining = delay - (curTime - starttime) // 从上一次到现在,还剩下多少多余时间 7 let context = this 8 let args = arguments 9 clearTimeout(timer) 10 if (remaining <= 0) { 11 fn.apply(context, args) 12 starttime = Date.now() 13 } else { 14 timer = setTimeout(fn, remaining); 15 } 16 } 17 }
防抖
function debounce(func, wait, immediate) {//immediate==true 立即执行 let timeout; return function () { let context = this; let args = arguments; 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); } } }
四、Vue使用npm的方式安装及使用:
安装
npm install throttle-debounce --save
使用
import { throttle, debounce } from 'throttle-debounce'
参考文档 https://www.npmjs.com/package/throttle-debounce