JavaScript 函数防抖
在前端开发中可能会遇到一些频发触发的事件,例如
- window 的 resize(浏览器窗口或者 HTML 对象改变大小)、scroll(滚动条事件)
- mousedown(鼠标在元素上按下事执行事件)、onmousemove(鼠标指针移动到元素上触发)
- keyup(按键被释放触发)、keydown(按键被按下触发)
举例
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | HTML<style>
 #root{
 width: 100%; height: 200px; line-height: 200px; text-align: center; color: #fff; background-color: #444; font-size: 30px;
 }
 </style>
 <div id='root'></div>
 <script src='./demo.js'></script>
 
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | dome.js;
 var conut = 1;
 var root = document.getElementById("root");
 function getUserAction() {
 
 root.innerHTML = conut++;
 }
 
 root.onmousemove = getUserAction;
 
 | 
效果如下

从图上可以看到从左边到右边一共触发了 160 多次 onmousemove 事件,同样执行了 160 多次 getUserAction 函数。
因为这个例子简单,浏览器可以处理的过来,如果换成请求, 频繁触发就会出现卡顿。
修改一下
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 |  dome.js
 var conut = 1;
 var root = document.getElementById('root');
 function getUserAction() {
 root.innerHTML = conut++;
 }
 function debounce(fn, wait) {
 var timeout;
 return function() {
 clearTimeout(timeout) 函数被执行了先清除先前定时器的返回值(传入一个错误的ID 给 clearTime 不会有任何影响(也不会抛出异常))
 timeout = setTimeout(fn, wait);
 }
 }
 root.onmousemove = debounce(getUserAction, 1000);
 
 
 | 
上面这个函数
分析一下上面的操作
- 鼠标移动触发 onmousemove 事件。
- onmousemove 事件调用 debounce 函数
- debounce 函数接收到 getUserAction, 1000 函数之后返回一个匿名函数-清除前面的定时器-执行新的定时器
然后只要鼠标移动就会 1-2-3 执行,直至鼠标停留超过一秒,才会执行 getUserAction 函数。
JavaScript 节流
节流就是如果持续触发事件,则每个一段时间,只执行一次事件。
主流有两种方法:使用时间戳, 设置定时器
使用时间戳
使用时间戳,当事件触发时,去除当前的时间戳,然后减去之前的时间戳,最开始可以设置为 0,如果大于设置的时间周期,就执行函数,然后更新时间戳为当前时间戳,如果小于,则不执行。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | function throttle(fu, wait) {var previos = 0;
 return () => {
 var now = +new Date();
 if (now - previous > wait) {
 
 fu();
 previous = now;
 }
 };
 }
 
 root.onmousemove = throttle(getUserAction, 1000);
 
 | 
使用定时器
当事件被触发的时候设置一个定时器,在触发事件,如果定时器存在则不执行,直至定时器执行然后执行函数,清空定时器。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | function throttle(fn, wait) {var timeout;
 return () => {
 
 if (!timeout) {
 
 timeout = setTimeout(() => {
 timeout = null;
 fn();
 }, wait);
 }
 };
 }
 root.onmousemove = throttle(getUserAction, 1000);
 
 |