- 页面优化:减少DOM操作,防止高频操作DOM造成页面挂掉
我们在平时开发的过程中,会有一些场景:如input框输入内容去调接口,以及onmousemove,resize,onscroll等,正常情况会频繁的去触发事件,造成不必要的性能消耗,为了避免这种情况就会通过函数防抖和函数节流来处理。
函数防抖
- _.debounce(func, [wait=0], [immediate])
事件响应函数(func)在一段时间(wait)后才会执行,如果在这段时间内再次触发该函数,会重新计算执行时间;当预定的时间内没有再次调用该函数,则执行func。
- 应用场景
- scroll时间滚动触发
- 搜索框输入查询
- 表单验证
- 按钮提交
- 浏览器窗口缩放,resize事件
// 防抖函数
function debounce(func, wait, immediate) {
let timeout;
let result;
let debounced = function() {
// this指向
let context = this;
// event
let args = arguments;
clearTimeout(timeout);
if (immediate) {
let callNow = !timeout;
timeout = setTimeout(function() {
timeout = null;
},
wait);
// 立即执行
if (callNow) {
result = func.apply(context, args);
}
} else {
timeout = setTimeout(function() {
func.apply(context, args);
},
wait);
}
return result;
}
debounced.cancel = function() {
clearTimeout(timeout);
timeout = null;
}
return debounced;
}
函数节流
- _.throttle(func, [wait=0], [options])
如果持续触发事件,每隔一段时间,只执行一次
- 应用场景
- DOM元素的拖拽功能实现
- 射击游戏
- 计算鼠标的移动距离
- 监听scroll滚动事件
// 节流函数
// 1、使用时间戳节流
// 第一次触发,最后一次不触发
function throttle(func, wait) {
let context;
let args;
// 上一次执行的时间戳
let old = 0;
return function() {
context = this;
args = arguments;
// 获取当前时间戳
let now = Date.now();
if (now - old > wait) {
// 立即执行
func.apply(context, args);
// 时间戳改变
old = now;
}
}
}
// 2、使用定时器
// 第一次不触发,最后一次触发
function throttle(func, wait) {
let timeout;
let context;
let args;
return function() {
context = this;
args = arguments;
if (!timeout) {
timeout = setTimeout(function() {
timeout = null;
func.apply(context, args);
},
wait);
}
}
}
// 3、时间戳和定时器结合
// 第一次触发,最后一次触发
function throttle(func, wait, options) {
let timeout;
let context;
let args;
// 上一次执行的时间戳
let old = 0;
return function() {
context = this;
args = arguments;
// 获取当前时间戳
let now = Date.now();
if (!options.leading && !old) {
old = now;
}
if (now - old > wait) {
// 第一次执行
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
// 立即执行
func.apply(context, args);
// 时间戳改变
old = now;
} else if (!timeout && options.trailing) {
// 最后一次执行
timeout = setTimeout(function() {
old = Date.now();
timeout = null;
func.apply(context, args);
},
wait);
}
}
}