js的防抖、节流
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js的防抖、节流相关的知识,希望对你有一定的参考价值。
参考技术A 防抖和节流,这是前端防止用户频繁调用同一个接口的方法,比如短时间重复点击上传同一个文件,短时间重复点击提交同一个评论,异步的操作还没给你带来反馈,于是你重复上传了多个文件,重复提交了多个评论。举例一个场景:为了例子更加简单,我们就用延迟来模拟一个后端接口返回的过程。
以上是一个发表评论的例子,由于接口一秒后才会响应评论反馈到界面上。
用户本意只是发布一条评论,但是由于接口需要响应时间,他以为自己的第一次点击没有生效于是就多点击了两次,结果显而易见,就是非用户本意的发布了三条一样的评论。
我们希望的是用户不要在请求还在进行的时候,频繁的重复发送请求。这时候就需要防抖节流了。
快速点击几次,还是只会发送一条评论。
但是缺点就是用户得到响应的时间更久了,得要算上延迟加上接口的响应。
速点击几次,还是只会发送一条评论。只有一条请求发布成功之后,才能够发布第二条请求,对于该场景十分合适。
浅谈 JS 的防抖和节流
浅谈 JS 的防抖和节流
前言:在了解防抖和节流之前,我们来认识聚焦事件和键盘事件
一、聚焦事件 (focus、blur、input)
- FocusEvent事件
焦点事件主要用于表单元素,以及超链接,使用点击或者tab可以切换汇聚焦距,当input聚焦是触发focus,失去焦点时触发blur
- foucs 是汇聚焦距 一般汇聚焦距时,会有outline样式
- blur 失去焦点
- 事件对象中relatedTarget为上一个失去焦点对象
<form>
<input type="text">
<input type="checkbox">
<input type="checkbox">
<select>
<option>aaaa</option>
<option>bbb</option>
<option>aaaa</option>
<option>aaaa</option>
<option>aaaa</option>
</select>
</form>
<a href="#">超链接</a>
<script>
var form=document.querySelector("form");
var input=document.querySelector("input");
input.addEventListener("focus",focusHandler);
input.addEventListener("blur",focusHandler);
// 获取单选按钮
var checkboxs=document.querySelectorAll("[type=checkbox]");
for(var i=0;i<checkboxs.length;i++){
checkboxs[i].addEventListener("focus",focusHandler)
}
// 获取下拉列表
var select=document.querySelector("select");
select.addEventListener("focus",focusHandler);
//获取超链接
var a=document.querySelector("a");
a.addEventListener("focus",focusHandler)
function focusHandler(e){
console.log(e.target,e);
if(e.type==="focus"){
e.target.style.outline="1px solid purple"
e.target.style.outlineOffset="0px";
}else if(e.type==="blur"){
e.target.style.outline="1px solid rgba(255,0,0,0)";
e.target.style.outlineOffset="5px";
}
}
</script>
失焦和聚焦主要用来判断表单验证
// input 输入事件主要用于文本框和多行文本框
var input=document.querySelector("input");
input.addEventListener("input",inputHandler);
function inputHandler(e){
console.log(e);
// e.data: "s" 本次输入的内容
// e.isComposing: false 输入法是否启动
// e.inputType 输入的类型
// insertCompositionText 输入插入
// historyUndo 历史返回
// insertText 插入文本
// deleteContentBackward 退格删除(删除前一个)
// deleteContentForward delete删除(删除后一个)
// deleteByCut 剪切删除
// insertFromPaste 粘贴插入
}
二、KeyboardEvent 键盘事件
<div></div>
<script>
var bool=false
// 按键是侦听document
document.addEventListener("keydown",keyHandler);
document.addEventListener("keyup",keyHandler);
// keydown不单纯在按下时存在,一直按着也会触发
function keyHandler(e){
if(e.type==="keydown"){
// 希望在什么地方加开关,这个开关指锁定这个位置
if(!bool){
console.log(e.type,e.keyCode);
}
bool=true;
return;
}else{
bool=false;
}
console.log(e.type,e.keyCode);
// e.code: "KeyJ" 键名
// key: "j" 键名
// keyCode: 74 键码
// which 键码
// 左 上 右 下 37,38,39,40
}
1、节流
文本框在输入的时候,如果每输入一次就判断一次,会造成效率太低,我们让它每间隔一段时间,再去验证。即指连续触发事件但是在 n 秒中只执行一次函数。
实现原理
给 input 设置一个属性,第一次触发事件时,属性值为 false,则往下执行,500毫秒后获取 input 的值,同时删除 ids 的值;第二次输入时,当500毫秒还没到时,ids 为 true ,则直接跳出,不去获取 value 值 。在500毫秒中,只执行一次函数。
节流的定时器写法:
<input type="text" name="text" id="user">
<script>
init();
function init(){
var user=document.getElementById("user");
user.addEventListener("input",inputHandler);
}
function inputHandler(e){
//判断,如果input.ids为false,则往下执行
if(this.ids) return;
//500毫秒后,执行showValue函数,同时删除ids的值
this.ids=setTimeout(function(elem){
//因为定时器函数会改变this指向,这里将this以参数的形式传进来
clearTimeout(elem.ids);
elem.ids=null;
showValue(elem.value);
},500,this);
}
//打印出input的值
function showValue(txt){
console.log(txt);
}
</script>
节流的时间戳写法:
<input type="text" name="text" id="user">
<script>
init();
function init() {
var user = document.getElementById("user");
user.addEventListener("input", inputHandler);
}
var lastTime=0;
function inputHandler(e) {
//每次触发事件获取当前时间
let nowTime=new Date().getTime();
//若时间间隔大于500毫秒,则执行代码
if(nowTime-lastTime>500){
//重新计时
lastTime=nowTime;
showValue(this.value);
}
}
//打印出input的值
function showValue(txt) {
console.log(txt);
}
</script>
2.防抖
防抖就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
keydown事件,当键盘按下时触发,如果键盘一直按下,则会一直触发这个事件,我们并不希望在事件持续触发的过程中那么频繁地去执行函数。这种情况防抖是比较好的解决方案。
===实现原理:
当持续触发keydown事件时,事件处理函数handle只在停止按键500毫秒之后才会调用一次,也就是说在持续触发keydown事件的过程中,事件处理函数handle一直没有执行。
节流和防抖有相似之处,我们在上面节流的基础上,该成下面的代码
<input type="text" name="text" id="user">
<script>
init();
function init() {
var user = document.getElementById("user");
user.addEventListener("input", inputHandler);
}
var ids=null;
function inputHandler(e) {
//每次输入,把前面的定时器清除,重新开启定时器
if(ids !== null) clearTimeout(ids);
ids=setTimeout(function(){
showValue(this.value);
},500)
}
//打印出input的值
function showValue(txt) {
console.log(txt);
}
</script>
防抖封装:
function debounce(fn, wait) {
var timeout = null; //定义一个定时器
return function () {
if (timeout !== null)
clearTimeout(timeout); //清除这个定时器
timeout = setTimeout(fn, wait);
}
}
// 处理函数
function handle() {
console.log(Math.random());
}
// 侦听事件
document.addEventListener("keydown", debounce(handle, 1000));
防抖和节流的区别?
- 节流是将多次执行变为每隔一段时间执行
- 防抖是将多次执行变为最后一次执行
以上是关于js的防抖、节流的主要内容,如果未能解决你的问题,请参考以下文章