防抖和节流
解决的就是事件被多次触发时,只执行最后一次事件,核心思想为了提升性能,减少DOM操作。
函数节流:指某些代码不可以在没有间断的情况下连续重复执行。
函数防抖:是指,一个频繁触发的事情只让最后一次执行。
区别:
函数节流
函数节流:一个函数执行一次后,只有大于设定的执行周期后才会执行第二次。有个需要频繁触发函数,出于优化性能角度,在规定时间内,只让函数触发的第一次生效,后面不生效。
时间戳实现函数节流
根据函数节流的原理,我们也可以不依赖 setTimeout实现函数节流。
function throttle(fn, delay) {
// 记录上一次函数触发的时间
var lastTime = 0;
return function() {
// 记录当前函数触发的时间
var nowTime = Date.now();
if (nowTime - lastTime > delay) {
// 修正this指向问题
fn.call(this);
// 同步时间
lastTime = nowTime;
}
}
}
测试代码:
// test
function testThrottle(e, content) {
console.log(e, content);
}
var testThrottleFn = throttle(testThrottle, 1000); // 节流函数
document.onmousemove = function (e) {
testThrottleFn(e, 'throttle'); // 给节流函数传参
}
定时器实现函数节流
function throttle(fn, delay) {
var timer;
return function () {
var _this = this;
var args = arguments;
if (timer) {
return;
}
timer = setTimeout(function () {
fn.apply(_this, args);
timer = null; // 在delay后执行完fn之后清空timer,此时timer为假,
throttle触发可以进入计时器
}, delay)
}
}
测试代码:
function testThrottle(e, content) {
console.log(e, content);
}
var testThrottleFn = throttle(testThrottle, 2000); // 节流函数
document.onmousemove = function (e) {
testThrottleFn(e, 'throttle'); // 给节流函数传参
}
如果一直在浏览器中移动鼠标(比如10s),则在这10s内会每隔2s执行一次testThrottle,这就是函数节流。
函数防抖
防抖函数:一个需要频繁触发的函数,在规定时间内,只让最后一次生效,前面的不生效。
function debounce(fn, delay) {
var timer = null;
return function () {
var _this = this; // 取debounce执行作用域的this
var args = arguments;
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(function () {
fn.apply(_this, args); // 用apply指向调用debounce的对象,
相当于_this.fn(args);
}, delay);
};
}
测试代码:
function testDebounce(e, content) {
console.log(e, content);
}
var testDebounceFn = debounce(testDebounce, 1000); // 防抖函数
document.onmousemove = function (e) {
testDebounceFn(e, 'debounce'); // 给防抖函数传参
}
vue 中使用
// 防抖
export function _debounce(fn, delay) {
var delay = delay || 200;
var timer;
return function () {
var th = this;
var args = arguments;
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(function () {
timer = null;
fn.apply(th, args);
}, delay);
};
}
// 节流
export function _throttle(fn, interval) {
var last;
var timer;
var interval = interval || 200;
return function () {
var th = this;
var args = arguments;
var now = +new Date();
if (last && now - last < interval) {
clearTimeout(timer);
timer = setTimeout(function () {
last = now;
fn.apply(th, args);
}, interval);
} else {
last = now;
fn.apply(th, args);
}
}
}
引用
import { _debounce } from "@/utils/common";
使用
methods: {
// 改变场数
changefield: _debounce(function(_type, index, item) {
// do something ...
}, 200)
}
// once 执行一次函数
function once(fn){
let done = false;
return function(){
if(!done){
done = true;
fn.apply(this, arguments);
}
}
}
let pay = once(function(money){
console.log(`花费了: ${money}`)
})
pay(3)
pay(3)