窗口的resize、scroll、输入框内容校验等操作时,如果这些操作处理函数是较为复杂或页面频繁重渲染等操作时,在这种情况下如果事件触发的频率无限制,会加重浏览器的负担,导致用户体验非常糟糕。此时我们可以采用debounce(防抖)和throttle(节流)的方式来减少触发的频率,同时又不影响实际效果。
在事件被触发n秒之后执行,如果在此期间再次触发事件,则重新开始计时。
我们模拟输入表单数据,自动获取后台数据,联想搜索,反馈回前台。监听keyup事件,如果每次输入一个字符,就发送一次请求,那么将在极短的时间发送非常多次请求,后台服务器不堪重负!
// 监听input值 模糊搜索 防止一直搜索
<input id="phone" type="text"/>
// 需要触发的函数
function debounce(d){
console.log("联想搜索phoneNumber:" + d)
}
let inp = document.querySelector("#phone");
// 输入触发的事件
function getPhone(fn,delay){
let timer;
// 使用闭包,保证每次使用的定时器是同一个
return (d)=>{
clearTimeout(timer);
timer = setTimeout(()=>{
fn(d);
// 结束之后清除定时器
clearTimeout(timer);
},delay)
}
}
let getPhoneDebounce = getPhone(debounce,1000);
inp.addEventListener('keyup',(e)=>{
getPhoneDebounce(e.target.value);
})
立即执行版的意思是触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果。
/**
* @param func 函数
* @param wait 延迟执行毫秒数
* @param immediate true 表立即执行,false 表非立即执行
*/
function debounce(func,wait,immediate) {
var timeout;
return function () {
var context = this;
var args = arguments;
if (timeout) clearTimeout(timeout);
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(function(){
timeout = null;
}, wait)
if (callNow) func.apply(context, args)
}
else {
timeout = setTimeout(function(){
func.apply(context, args)
}, wait);
}
}
}
如果持续触发一个事件,则在一定的时间内只执行一次事件。
我们模拟射击,首先第一次点击射击的时候,打出一发子弹,当以极短的时间再次点击射击的时候,由于需要‘冷却’——也就是节流,再次点击无效,当冷却时间过了之后,再次点击射击,则继续下一次射击
准备工具:一个射击的函数shot, 一个判断射击间隔是否结束的函数nextShot,一个触发射击的按钮,判断射击是否结束的定时器timer
基本思路:第一次点击按钮的时候,触发shot,当继续点击的时候,射击无效,只有过了定时器设置的时间才可以继续射击。
// 模拟射击
<button id="shot">射击</button>
function shot(){
console.log('射击')
}
let btn = document.querySelector('#shot');
function nextShot(fn,delay){
let timer;
// 闭包原理同上
return ()=>{
// 定时器存在,无法射击
if(timer){
console.log('禁止射击');
}else{ // 定时器不存在,射击,并设置定时器
fn();
timer = setTimeout(()=>{
// 定时器结束,可以射击
clearTimeout(timer);
timer = null;
},delay)
}
}
}
let start = nextShot(shot,20);
btn.addEventListener('click',()=>{
start();
})
在一个input搜索框中输入文本,如果2s内可能会有很多次input的onChange事件,每次都触发一个API请求,明显不合理,所以此时需要debounce节流函数,2s之内的所有输入只会请求一次API
在限制的时间内持续触发事件的时候,函数是完全不执行的,非立即执行版,等最后一次触发结束的一段时间之后,再去执行,节流的意思是让函数有节制地执行
一种是立即执行:频繁触发事件,第一次触发时执行函数,后面触发不会执行,停止触发,间隔一定时间之后再触发事件,函数才会再次执行
函数防抖和节流都是对高频动作触发回调函数的一个优化,实现方式上有类似之处。先从使用场景做个区分。
节流:在一定时间内连续触发某事件,在这段时间段内只执行首次触发的那一次。1s内执行第一次,防抖:在一定时间内连续触发某事件,在这段时间内只执行最后一次触发的那一次。最后一次延时1s后执行
概念:在规定的间隔时间范围内不会重复触发回调,只有大于这个时间间隔才会触发回调,把频繁触发变为少量触发。类似于技能CD。应用:点击按钮,轮播图点击左右箭头。
节流是指避免过于频繁地执行某个功能,例如保存按钮。 为了避免重复提交或者服务器的考虑,往往需要限制点击行为,否则接口会被频繁请求。 之前基本都是通过js控制节流问题
今天给大家带来的是Vue 2 中的实现 CustomRef 方式防抖/节流这篇文章,前几天利用 customRef 实现了在 vue 3 中的极致防抖/节流的新方式。在前端的开发过程中,在涉及到与用户交互的过程中是基本上都是需要处理的
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!