函数防抖
-
函数防抖:高频率触发(比如10分钟内一直触发)的时候,只执行一次,第一次或者最后一次。重点在只执行一次。
在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。 -
应用场景
1. 手机号、邮箱输入检测 2. 搜索框搜索输入(只需最后一次输入完后,再放松Ajax请求) 3. 窗口大小resize(只需窗口调整完成后,计算窗口大小,防止重复渲染) 4. 滚动事件scroll(只需执行触发的最后一次滚动事件的处理程序) 5. 文本输入的验证(连续输入文字后发送 AJAX 请求进行验证,(停止输入后)验证一次就好
-
code
css<style> .content { width: 100%; height: 300px; background-color: aqua; display: flex; justify-content: center; align-items: center; } span { color: azure; font-size: 40px; } </style>
html
<div class="content"> <span>0</span> </div> <button class="pre">click me action first time</button> <button class="delay">click me action last time</button>
js
let oCon = document.querySelector('.content') let oSpan = document.querySelector('span') let oPre = document.querySelector('.pre') let oDelay = document.querySelector('.delay') oPre.onclick = debouncePrev(add,1000) oDelay.onclick = debounceDelay(add,1000) oCon.onmousemove = throttle(add,1000) function add(){ let num = Number(oSpan.innerHTML) oSpan.innerHTML = ++num } /** * 立即执行 * 连续点击执行第一次 */ function debouncePrev(func,delay=160){ let timer return function(){ if(timer) clearTimeout(timer) let action = !timer timer = setTimeout(() => { timer = null }, delay); if (action) { func.apply(this,arguments) } } } /** * 立即执行 * 连续点击执行最后一次 */ function debounceDelay(func,delay=160){ let timer return function(){ clearTimeout(timer) let _this = this, args = arguments; timer = setTimeout(()=>{ func.apply(_this,args) },delay) } }
函数节流
-
函数节流:高频率触发的时候,间隔固定时间内执行一次,会稀释执行事件。重点在稀释触发事件。
-
应用场景
1. DOM元素的拖拽功能实现(mousemove) 2. 射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹) 3. 计算鼠标移动的距离(mousemove) 4. 搜索联想(keyup) 5. 滚动事件scroll,(只要页面滚动就会间隔一段时间判断一次)
-
code
/** * 时间戳版 * 立即执行 */ function throttle(func,delay=350){ let timer; let prev = Date.now() console.log('prev'+prev); return function(){ let now = Date.now() console.log('now'+now); if (now - prev > delay) { console.log('ll'); prev = now func.apply(this,arguments) } } } /** * 定时器版 * delay固定时间后执行 */ function throttle(func,delay= 350){ let timer return function(){ let _this = this let args = arguments; if(!timer){ timer = setTimeout(() => { // console.log(timer); timer = null func.apply(_this,arguments) // clearTimeout(timer) //此时 time= true }, delay); } } }
总结
封装代码
/*
* @desc 函数防抖
* @param func 目标函数
* @param delay 延迟执行毫秒数
* @param immediate true - 立即执行, false - 延迟执行
*/
function debounce(func, delay, immediate = false) {
let timer;
return function () {
console.log(immediate);
if (immediate) {
let action = !timer;
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
timer = null;
}, delay);
if (action) func.apply(this, arguments);
} else {
let _this = this;
let args = arguments;
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(_this, args);
}, delay);
}
};
}
/*
* @desc 函数节流
* @param func 目标函数
* @param delay 延迟执行毫秒数
* @param immediate true - 立即执行, false - 延迟执行
*/
function throttle(func, delay, immediate) {
let timer;
let prev = Date.now();
return function () {
let _this = this;
let args = arguments;
if (immediate) {
let now = Date.now();
if (now - prev > delay) {
prev = now;
func.apply(this, arguments);
}
} else {
if (!timer) {
timer = setTimeout(() => {
timer = null;
func.apply(_this, args);
}, delay);
}
}
};
}