在线查看效果移动鼠标触发
1.防抖(立即执行/非立即执行)
- 什么是防抖:一个事件在触发后,设置定时器,若n秒内该事件没有再次发生,那么执行这个函数,如果n秒内该事件再次发生了,那么定时器重新开始计时。
- 应用
- 每次 resize / scroll 触发统计事件
- 文本输入的验证 (连续输入文字后发送AJAX请求进行验证,验证一次就好)
- 1.1 非立即执行版
//防抖(非立即执行)
function debounce_1(fn,wait){
var timerId = null;
return function(){
var context = this
var args = arguments
clearTimeout(timerId);
timerId = setTimeout(() => {
fn.apply(context,args)
},wait)
}
}
- 1.2 立即执行版
//防抖(立即执行)
function debounce_2(fn,wait){
var timerId = null;
var flag = true;
return function(){
var context = this
var args = arguments
clearTimeout(timerId);
if(flag){
fn.apply(context, args);
flag = false
}
timerId = setTimeout(() => { flag = true},wait)
}
}
- 1.3 合并版
//防抖(合并版)
function debounce_merge(fn,wait = 500,isImmediate = false){
var timerId = null;
var flag = true;
return function(){
var context = this
var args = arguments
clearTimeout(timerId )
if(isImmediate ){
if(flag){
fn.apply(context,args)
flag = false
}
timerId = setTimeout(function(){
flag = true
},wait)
}else{
timerId = setTimeout(function(){
fn.apply(context,args)
},wait)
}
}
}
2.节流(立即执行/非立即执行)
- 什么是节流:若一个函数在一段时间内持续高频触发,节流后将使得该函数在这段时间内每隔固定时间才执行一次
- 应用
- 与mousemove keyup/keydown 等相密切联系的函数
- 2.1 非立即执行版
//定义函数
//节流(非立即执行)
function throttle_1(fn,wait){
var flag = true;
return function(){
var context = this
var args = arguments
if(flag){
flag = false
setTimeout(() => {
fn.apply(context,args)
flag = true
},wait)
}
}
}
- 2.2 立即执行版
//节流(立即执行)
function throttle_2(fn,wait){
var flag = true;
return function(){
var context = this
var args = arguments
if(flag) {
fn.apply(context,args);
flag = false;
setTimeout(() => {
flag = true
},wait)
}
}
}
- 2.3 合并版
//节流(合并)
function throttle_merge(fn,wait = 500,isImmediate = false){
var flag = true;
return function(){
if(flag == true){
var context = this
var args = arguments
flag = false
isImmediate && fn.apply(context,args)
setTimeout(() => {
!isImmediate && fn.apply(context,args)
flag = true
},wait)
}
}
}
3.补充
- 看文字远不如亲自操作了解得透彻,希望还不太明白的小伙伴在下面演示代码具体操作操作
- 这里的几个函数都是使用的
setTimeout
来实现的,也可以使用Date.now()
来实现,思路一样,偷个懒就不写了,嘿嘿; - 合并版的
debounce(fn,wait,isImmediate)
throttle(fn,wait,isImmediate)
4.演示代码
截图
在线查看效果
<!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>Document</title>
<style>
body{height: 1200px;}
div{width: 100%;background-color: lightcyan;overflow: hidden;}
p{float: left;width: 10px;height:10px;background-color: pink;margin: 1px;}
</style>
</head>
<body>
防抖(非立即执行) <div id="d1_1"></div>
防抖(立即执行) <div id="d1_2"></div>
节流(非立即执行) <div id="d2_1"></div>
节流(立即执行) <div id="d2_2"></div>
<!-- 原生 <div id="d3"></div> -->
</body>
<script>
//防抖(非立即执行)
function debounce_1(fn,wait){
var timerId = null;
return function(){
clearTimeout(timerId);
timerId = setTimeout(() => {
fn.apply(this,arguments)
},wait)
}
}
//防抖(立即执行)
function debounce_2(fn,wait){
var timerId = null;
var flag = true;
return function(){
clearTimeout(timerId);
if(flag){
fn.apply(this,arguments);
flag = false
}
timerId = setTimeout(() => { flag = true},wait)
}
}
//节流(非立即执行)
function throttle_1(fn,wait){
var flag = true;
return function(){
if(flag == true){
flag = false
var timer = setTimeout(() => {
fn.apply(this,arguments)
flag = true
},wait)
}
}
}
//节流(立即执行)
function throttle_2(fn,wait){
var flag = true;
var timer = null;
return function(){
if(flag) {
fn.apply(this,arguments);
flag = false;
timer = setTimeout(() => {
flag = true
},wait)
}
}
}
//定义事件函数
function debounce_fn1(){ addElement(d1_1) }
function debounce_fn2(){ addElement(d1_2) }
function throttle_fn1(){ addElement(d2_1) }
function throttle_fn2(){ addElement(d2_2) }
// function origin(){ addElement(d3) }
//注册事件
var body = document.getElementsByTagName('body')[0]
body.addEventListener("mousemove",debounce_1(debounce_fn1,500))
body.addEventListener("mousemove",debounce_2(debounce_fn2,500))
body.addEventListener("mousemove",throttle_1(throttle_fn1,500))
body.addEventListener("mousemove",throttle_2(throttle_fn2,500))
// body.addEventListener("mousemove",origin)
//辅助函数
function addElement(f){
var node=document.createElement("p");
f.appendChild(node);
}
</script>
</html>