先简单介绍一下 addEventListener()方法
addEventListener()方法用于指定元素添加监听事件。且同一元素目标可以重复添加,不会覆盖之前相同事件,配合removeEventListener() 方法来移除事件。
addEventListener(参数1,参数2,参数3)
参数1:事件名称、字符串,必填
事件名称不用带‘on’前缀,点击事件直接写:‘click’,键盘放开事件写:‘keyup’
参数2:执行函数,必填
① 填写需要执行的函数,如:function(){代码…}
② 当目标对象事件触发是,会传入一个事件参数,参数名称可自定义,如填写event,不需要也可以不填写。事件对象的类型取决于特定的事件。例如,click事件属于MouseEvent(鼠标事件)对象。
function(event){
console.log(event)
}
参数3、触发类型,布尔型,可空
true - 事件在捕获阶段执行
false - 事件在冒泡阶段执行,默认是false
前言:
(1)搜索需求
搜索的逻辑就是监听用户输入事件,等用户输入完成之后把数据发送给后端,后端返回匹配数据,前端显示数据到页面。如果只要用户输入就发请求,这样会给后端造成请求压力,需要控制请求的频率。
(2)页面无限加载数据
页面无限加载数据的逻辑就是监听用户用户滚动事件,在用户滚动的过程中,去请求下一页的数据来显示到页面。,那么只要滚动就去发请求,同样会造成后端请求压力,需要控制请求的频率。
以上两种看起来都是控制请求频率的问题,但是需求有细微的差别:搜索是用户在输入中输入多次,只有等用户短暂停止输入之后,就去发送请求,此时就需要防抖去实现。滚动加载数据是在用户滚动页面的过程中每间隔一段时间就去请求,即使用户一直滚动,都会去请求,而不是等用户停止滚动才去请求,此时就需要使用节流去实现。
一、 防抖
防抖是将多次操作变成一次,只允许有一个存在。也就是在固定时间内,事件只允许发生一次。
例如:
<input placeholder="请输入电话" />
//不使用防抖时: 输入一次就请求一次
let telInput = document.querySelector('input');
telInput.addEventListener('input', (e) => {
console.log('发起请求'); //输入一次就请求一次
})
原理:
用户每一次触发事件都会延迟执行,在设置延迟定时器执之前都会把上一次延迟定时器清除,最终只有用户连续触发这个事件的间隔时间超出我们设置的参数wait毫秒之后,该事件才会触发一次
(用户多次触发事件,在用户一直触发事件中,事件不会执行,只有在用户停止触发事件一段时间之后再执行这个事件一次。)
//防抖封装 fn:传方法 wait:等待的时间
function antiShake(fn, wait) {
let timeOut = null;
// 闭包的设计 es6的写法
return args => {
if (timeOut) clearInterval(timeOut); // 如果定时器已经存在 就清除
timeOut = setTimeout(fn, wait); //如果没有就创建一个定时器
// timeOut=setTimeout(()=>{},timeOut); //上面是简写
}
}
// 模拟一个数据请求的方法
function demo() {
console.log('发起请求');
}
//使用防抖封装
telInput.addEventListener('input', antiShake(demo, 2000)); //防止数据抖动 不管输入多少个 等停下来两秒后才会发送请求
二、节流
节流:保证一定时间内,只调用一次函数,也就是一定时间内的多个合为一个
应用场景:①提交表单 ②高频监听事件
<div class="box" style=" background-color: aquamarine;
width: 100px;
height: 100px;">
</div>
//不使用节流时
let box = document.querySelector('.box')
box.addEventListener('mousemove', (e) => { //mousemove 鼠标被移动
console.log("发起请求"); // 鼠标一移动就触发事件
})
原理:
用户每一次触发事件都会设置一个延迟定时器,但是如果已经设置了延迟定时器就会等上一次延迟定时器执行之后才会开启下一个定时器,这样用户一直触发事件,事件会每间隔一段时间执行一次
(用户多次触发事件,在用户一直触发事件过程中事件会每间隔一段时间执行一次,会执行多次。)
//使用节流
// 节流
function throttle(event, time) {
let timer = null;
// es5的写法
return function() {
if (!timer) {
timer = setTimeout(() => {
event();
timer = null;
}, time)
}
}
}
// 模拟一个数据请求的方法
function demo() {
console.log('发起请求');
}
//使用节流
box.addEventListener('mousemove', throttle(demo, 2000)) //不管移动多少次 都两秒请求一次