防抖与节流
这次项目中,由于有大量的滚动事件,为了减少事件的触发,提高网站的性能,我准备使用防抖与节流的方式对这些滚动事件进行控制。
防抖
当我们给一个按钮绑定一个点击事件时,每当我们点击一次按钮都会触发一次事件绑定的函数,如果这个事件是提交一类的事件,显然我们不希望用户频繁点击按钮重复提交数据,这时我们就要对这个点击事件进行防抖处理,所谓的防抖就是当我们重复点击按钮时,事件仅会触发一次,只有在一定时间间隔后再次点击才会再次执行。防抖常用于防止用户频繁向服务器发送请求,或者避免浏览器的画面过于频繁地重绘。
我们现在实现一个防抖函数,HTML只有一个按钮:
```javascript
` <button id="button">提交</button>`
现在给这个按钮添加监听点击事件:
` let btn = document.getElementById("button");
btn.addEventListener('click', subit, false)`
然后我们要用一个函数包装这个提交的函数,让它延迟执行,并在每一次点击时重置延迟时间,同时,第一次执行是没有延迟时间的
` btn.addEventListener('click', debounce(subit, 2000), false)`
` function debounce(fn, timer) {
//由于监听时间的回调函数返回的必须是一个函数,因此return之前的部分会在也页面加载时立即执行,相当于初始化
let t = null;
return function() {
//第一次执行时t的值为null,因此第一次点击时firstclick的值是true
let firstclick = !t;
//如果t的值的false(null),清除延时器
if (t) {
clearTimeout(t)
}
//第一次firstclick取的值是true,会立即执行函数
if (firstclick) {
//这里我们的的fn中可能会用到e等window对象,
// 但在包装函数中,e会变成一个形参,当出现多参数时会混乱
// 因此我们需要把arguments的类数组对象绑定为fn的第二个参数,arguments,
//此时this指向触发函数的button,因此绑定的argument就是button的参数列表,也就是该函数原本的参数列表
fn.apply(this, arguments)
}
//给t赋值,如果在timer的时间里计时器没有被清除,那么t的值被重置,重新恢复最初状态
t = setTimeout(() => {
t = null;
}, timer);
}`
节流
节流相比于防抖更容易使用,节流的原理是当需要连续触发事件时,不会一直触发,而是每隔一段事件触发一次
function throttle(fn, delay) {
// 初始化一个时间
let begin = 0;
return function() {
// 获取当前时间戳
let cur = new Date().getTime();
// 只有两次触发的时间间隔大于指定值,才会触发事件函数
if (cur - begin > delay) {
fn.apply(this, arguments);
//bigin设置为当前时间戳
begin = cur;
}
}
}