防抖节流个人看法讲解
一、对防抖节流的认知
我以为的防抖节流:
实际上的防抖节流:
详细请往下看
二、我开始正经了
-------------------防抖 -------------------
首先先看一个问题:
公司给了一个电商里一个搜索框的小模块,需求:
1.用户输入关键词
2.系统给出推荐的相关商品
解决思路:简单,一个输入框加一个oninput事件,事件里执行推荐操作不就搞定啦?错错错!如果你是这样想的,你会得到下面的效果:
你会发现,用户每输入一个字你就进行一次处理,我这里举例用的是简单的console.log(this.value + "爆款");
,正常写项目里,你肯定要向后台发请求拿到数据库里的推荐吧?用户每输入一个字你就发一次请求,以这个频率发请求,一秒钟发7、8次,呵呵~你等着呗管后台的同事骂吧你。
来了来了 防抖来了
防抖思路:设置一个定时器,让用户停止输入 后一定时间才执行推荐操作(发请求)
具体实现:
1.用户首次向input输入框进行输入,设置一个定时器:1000毫秒后输出推荐用户的商品
2.1000毫秒以内用户再次向input输入框进行输入,删掉之前的定时器,重新设置一个新的定时器:开始重新计时
3.当前时间距离用户最后一次触发事件的间隔时间达到 特定值(假设是1000毫秒)时,开始执行处理程序:也就是输出推荐用户的商品选择。
代码实现:
首先把用户停止输入后,系统执行的推荐操作写好
// 创建一个函数:用于向用户推荐商品
function recommend(){
//这里做的事情就是:用户输入关键字,系统想用户推荐可能的商品
console.log(this.value); //此处的this指向input
console.log(this.value + "男款");
console.log(this.value + "爆款");
}
然后写一个封装好的防抖函数
//防抖函数 :作用,为函数添加防抖功能
function debounce(fn, delay) {
let timer
//返回一个函数
return function () {
if (timer) {
//不断的清除定时器,一直到停留间隔达到1秒
clearTimeout(timer)
}
//设置一个定时器
timer = setTimeout(() => {
fn.call(this)
}, 1000)
}
}
最后把前面推荐操作函数,放到防抖函数里执行即可。全部代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text" >
<script>
// 1.拿到input输入框
const input = document.querySelector('input')
// 2.给input绑定事件
// 创建一个函数:用于向用户推荐商品
function recommend(){
//这里做的事情就是:用户输入关键字,系统想用户推荐可能的商品
console.log(this.value); //此处的this指向input
console.log(this.value + "男款");
console.log(this.value + "爆款");
}
input.oninput = debounce(recommend,1000)
//防抖函数 :作用,为函数添加防抖功能
function debounce(fn, delay) {
let timer
//返回一个函数
return function () {
if (timer) {
//不断的清除定时器,一直到停留间隔达到1秒
clearTimeout(timer)
}
//设置一个定时器
timer = setTimeout(() => {
fn.call(this)
}, 1000)
}
}
</script>
</body>
</html>
实现效果:
到这里你可能会是这种状态
当然,初级的防抖就是差不多这样的原理了,还有其它不用定时器的方法,不过也大同小异了。注意!!!是初级,实际开发中要注意的地方还多着呢。
三、节流
防抖,我知道了,节流又是个什么玩意呢?别急,慢慢听我解释。
前面防抖是为了防止用户还没输入结束(事件终止)就发送请求,造成资源浪费。
这里节流除了担心用户还没输入结束(事件终止)就发送请求之外,还担心某些用户一直不终止动作,导致我们一直不能执行下一步操作发送请求,很被动很笨的呀,你懂不懂
这里有个例子更适合解释节流:鼠标滑轮在浏览器上滚动
你会发现,你轻轻滚一下滑轮,起码触发了十几次事件,你一直滚个不停,它就一直不发请求。很不合理,往常都是滚一下动一下的,到你这还得蓄力了?
特别是某些人就有习惯,他就喜欢一直滚着滑轮,一个劲的滚,滚个不停,咋了,这时候你还能打电话叫他慢点?
加上防抖之后,他不停下来你就发不了请求,咋办?这里更简单,直接给他弄个定时器,一秒钟后执行就好了,一秒后不管是不是还在滚动,都执行操作。
还是一样的味道
首先封装一个节流函数
function throttle(fn, delay) {
let flag = true
return function () {
if (flag) {
setTimeout(() => {
fn()
// 设置flag为true
flag = true
}, delay)
}
flag = false
}
}
再写一个对用户操作后的处理函数
function () {
console.log('我滚动了滑轮');
}
完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body{
height: 10000px;
}
</style>
</head>
<body>
<script>
window.onscroll = throttle(function () {
console.log('我滚动了滑轮');
},1000)
function throttle(fn, delay) {
let flag = true
return function () {
if (flag) {
setTimeout(() => {
fn()
// 设置flag为true
flag = true
}, delay)
}
flag = false
}
}
</script>
</body>
</html>
效果:
四、总结
防抖:高频触发事件,只要最后一次事件处理程序内部的执行成果
节流:控制高频事件的触发次数