防抖节流函数是什么
防抖:触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间。通俗来说就是n个事件发生了,我只认最后一次。比如一个需求,一个输入框,当我输入内容之后会请求接口搜索出与输入框内容相关的数据,这个输入框的change事件在输入的时候高频触发,如果每次改变都去请求接口会造成很大的性能问题,这个时候的做法可能是当我停止输入一秒之后再去请求接口,就只会发起一次请求
节流:高频事件触发的时候,每隔n秒执行一次。防抖函数的弊端–当我一直输入一直不停那么函数就一直不会被执行,这很容易被用户以为该程序是不是卡了,造成不好的用户体验,此时每隔n秒执行一次函数,给用户反馈就很重要了,这就是节流的用法
1.防抖函数封装
在项目中新建一个js文件utils.js
const utils = {}
/**
* 防抖
* @param {*} fn 需要防抖的方法
* @param {*} delay 防抖时间
* @returns
*/
utils.debounce = function(fn, time) {
// 等待的时间默认200ms
let delay = time || 200;
let timer = null;
return function () {
const _this = this;
// 保存调用时传来的参数
const args = arguments;
// 每次事件被触发时,都清除之前的旧定时器
if (timer) {
clearTimeout(timer);
}
// 函数延迟执行
timer = setTimeout(function () {
fn.apply(_this, args);
}, delay);
};
}
export default utils;
调用封装的防抖函数
// 先引入函数
import utils from '@/assets/js/utils.js'
// 方法,注意此处不能使用箭头函数,否则this指向会有问题
handleScroll:utils.debounce(function(e) {
// 此处写自己的逻辑
}, 500)
2.防抖函数先执行再等待
此时的问题是我一直在操作怎么没有反应呢,防抖函数上面说了是只认最后一次,可不可以让我先执行一次你再去等待啊,那么我们上面的函数升级一下,增加一层anOnce立即执行的判断,当我传入atOnce时就先执行一次,否则还是按正常的防抖函数走,满足不同的使用场景
/**
* 防抖
* @param {*} fn 需要防抖的方法
* @param {*} delay 防抖时间
* @param {*} atOnce 是否需要立即执行
* @returns
*/
utils.debounce = function(fn, time, atOnce) {
let delay = time || 200;
let timer = null;
let count = 0;
return function () {
const _this = this;
const args = arguments;
// 如果是立即执行
if (atOnce) {
// 第一次直接执行不用等
if (count == 0) {
fn.apply(_this, args);
count ++;
} else {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(function () {
fn.apply(_this, args);
}, delay);
}
//
} else {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(function () {
fn.apply(_this, args);
}, delay);
}
};
}
调用
handleScroll:utils.debounce(function(e) {
// 此处写自己的逻辑
}, 500, true)
3.节流函数的封装
/**
* 节流
* @param {*} fn 需要节流的方法
* @param {*} interval 多久执行一次节流
* @returns
*/
utils.throttle = function(fn, time) {
let last;
let timer;
let interval = time || 200;
return function () {
const _this = this;
const args = arguments;
let now = +new Date();
if (last && now - last < interval) {
clearTimeout(timer);
timer = setTimeout(function () {
last = now;
fn.apply(_this, args);
}, interval);
} else {
last = now;
fn.apply(_this, args);
}
}
}
调用
handleScroll:utils.throttle(function(e) {
// 此处写自己的逻辑
}, 500)
4.lodash库防抖节流函数的使用
文档
文档里面很详细,也同样封装了是否防抖前执行,节流前执行
// 安装
npm i --save lodash
// 引入
import _ from 'lodash'
// 防抖
handleScroll:_.debounce(function(e) {
// 此处写自己的逻辑
}, 500)
// 节流
handleScroll:_.throttle(function(e) {
// 此处写自己的逻辑
}, 500)
如有错误的地方请指正