为了加深自己对防抖+节流的理解,实现两个简单的案例来加深自己的印象。
一、函数节流(throttle)
通过实现一个拖拽
Dom
元素小案例来加深对函数节流的理解
- 情景:当
drag
拖拽事件执行,1秒内调用多次DragFn函数。- 实现效果:如果1秒内执行了多次函数,那么函数1秒只能执行一次(5s执行5次)。
- drag.js - 示例code
"use strict";
// 函数节流(throttle) - 情景:当drag拖拽事件执行,1秒内调用多次DragFn函数。
// 实现效果:如果1秒内执行了多次DragFn函数,那么DragFn函数1秒只能执行一次(5s执行5次)。
(function(){
const box_dom = document.getElementsByClassName('box')[0];
let isDrag = false; //拖拽状态
let drag_position = {}; //记录开始拖拽时元素坐标
// 开始拖拽
// clientX/clientY - 鼠标指针的水平/垂直坐标
box_dom.addEventListener('dragstart',function(e){
if(e.target === box_dom){
isDrag = true;
//getBoundingClientRect方法返回元素的大小及其相对于视口的位置
let {left,top} = box_dom.getBoundingClientRect();
drag_position.left = e.clientX - left;
drag_position.top = e.clientY - top;
}
},false)
const DragFn = throttle(Fn,1000);
// 拖拽移动
box_dom.addEventListener('drag',DragFn,false);
// 拖拽结束
box_dom.addEventListener('dragend',function(e){
isDrag = false;
},false)
function throttle(fn,timer){
let init_time = 0;
// 回调函数提供给drag事件
return function(...args){
let now_time = +new Date();
if(now_time-init_time > timer){
init_time = now_time;
fn.apply(this,args);
}
}
}
// 节流执行的函数
function Fn(e){
e.preventDefault();
if(isDrag&&e.clientX!==0){
let t_left = e.clientX - drag_position.left;
let t_top = e.clientY - drag_position.top;
box_dom.style.left = t_left+'px';
box_dom.style.top = t_top+'px';
const timer = new Date();
console.log(`${timer.getMinutes()}:${timer.getSeconds()} ---------- Drag Dom----------`);
}
}
})()
复制代码
二、函数防抖(debounce)
input
如果2秒之内继续输入内容,那么计时器重新回到2秒,函数不执行(回表),等待输入完成2秒时间到后执行函数。
- 作用:例如通过监听
input keydown
事件,请求搜索内容,为了避免过于频繁的执行请求,需要使用函数防抖来实现优化。
- search.js - 示例code
"use strict";
// 函数防抖(debounce) - 情景:当input输入内容时,像后台请求搜索内容。
// 实现效果:如果2秒之内重新输入,那么计时器重新回到2秒函数不执行(回表),等待输入完成2秒时间到后执行函数。
(function(){
const SeachDom = document.getElementsByTagName('input')[0];
const KeyDownFn = debounce(Fn,2000);
SeachDom.addEventListener('keydown',KeyDownFn);
function debounce(fn,timer){
let timer_out = null;
return function(...args){
// 清除计时器
if(timer_out) clearTimeout(timer_out);
timer_out = setTimeout(()=>{
fn.apply(this,args);
},timer)
}
}
// 请求搜索内容操作
function Fn(e){
console.log(e.target.value, '<------search values');
}
})();
复制代码
三、HTML 代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>函数防抖/节流Demo</title>
<style>
html,body{
width: 100%;
height: 100%;
padding:0;
margin:0;
}
.box,.debounce{
width: 200px;
height: 200px;
background: skyblue;
position: absolute;
left: 20px;
top: 20px;
border-radius: 10px;
}
.debounce{
top: 300px;
background: yellowgreen;
line-height: 200px;
text-align: center;
padding: 0 20px;
}
.debounce input{
top: 300px;
display: inline-block;
height: 30px;
width: 100%;
font-size: 16px;
padding-left: 10px;
}
.box{
cursor: move;
}
.box>p,.debounce>p{
margin: 0;
display: flex;
height: 100%;
line-height: 30px;
flex-direction: column;
justify-content: center;
align-items: center;
color: #333;
}
</style>
</head>
<body>
<section class="box" draggable="true">
<p>
<span>
拖拽节流
</span>
<span>
(1秒移动一次)
</span>
</p>
</section>
<section class="debounce">
<p>
<input type="text" placeholder="搜索防抖" class="search-input">
<br/>
<span>
输入完成2秒后
</span>
<span>执行搜索请求</span>
</p>
</section>
<!-- 拖拽 -->
<script src='./src/drag.js'></script>
<!-- 搜索 -->
<script src='./src/search.js'></script>
</body>
</html>
复制代码