前言
在类似scroll、resize事件中执行大量DOM操作或者计算时,就会出现再次触发事件而上一次事件中的DOM操作和计算还没完成的情况,结果浏览器掉帧了,导致性能下降,影响用户体验。而函数节流和函数防抖,两者都是优化高频率执行js代码的一种手段。因此,可以用以下两种方式优化代码。
概念
一、函数防抖:
指频繁触发的情况下,只有足够的空闲时间,才执行代码一次,也就是让某个函数在上一次执行后, 满足等待某个时间内不再触发此函数后再执行, 而在这个等待时间内再次触发此函数, 等待时间会重新计算.实际需求多数为停止操作n毫秒后执行后续处理 。
二、函数节流:
指为这个操作(函数)预先设定一个执行周期,当调用动作的时刻>=执行周期则执行该动作,然后进入下一个新周期,否则不执行。简单来说就是你的js方法在一定时间内只跑一次(频率)。
适用场景
一、函数节流:
场景一:页面元素滚动的时候,触发某个事件。
场景二:高频率点击表单提交按钮,表单重复提交。
实现要点:声明一个变量当标志位,记录当前代码是否在执行,
var valve = true; //标志位
document.getElementById("box").onscroll = function(){
// 判断是否已空闲,如果在执行中,则直接return,如果空闲,则可以正常触发方法执行。
if(!valve){
return;
}
valve = false; //关闭
//要执行的函数
something()
};
function something(){
setTimeout(function(){
console.log("函数节流");
valve = true;//执行周期完成后打开阀门,允许再次调用
}, 300);
}
二、函数防抖:
场景一:表单验证,用户停止输入后,然后开启验证
场景二:轮播图等
实现要点:巧用setTimeout做缓存池,可以轻易地清除待执行的代码。
// 函数防抖
var timer = false;
document.getElementById("box").onscroll = function(){
clearTimeout(timer); // 清除未执行的代码,重置回初始化状态
timer = setTimeout(function(){
//滚动事件停止300毫秒后 调用
console.log("函数防抖");
}, 300);
};
案例
一(防抖)、假设网站有个搜索框, 用户输入文本我们会自动联想匹配出一些结果供用户选择,我们可能首先想到的做法就是监听keypress事件, 然后异步查询结果. 但是如果用户快速的输入了一串字符, 假设是10个字符, 那么就会在瞬间触发10次请求, 这无疑不是我们想要的, 我们想要的是用户停止输入的时候才去触发查询的请求.
二(防抖vs节流)
假设网站有登录框, 用户登录信息后,自动验证用户信息,首先监听输入框oninput事件, 然后异步验证登录信息.验证成功点击登录按钮,进行登录操作。 但是这样的话用户每输入了个字符, 就会调用一次oninput事件,那么就触发1次请求, 这无疑不是我们想要的, 我们想要的是用户停止输入的时候才去触发验证的请求.(##这里可以用函数防抖处理 ,几百毫秒后执行验证信息##)
验证成功后,进行登录操作,调用登录接口,但是如果高频率点击登录按钮,会不停调用登录接口,(##这里可以用函数节流处理 ,在上次登录接口调用完成之前,不能再次调用##)