1 防抖和节流的原理
防抖:
事件频繁发生
。比如说,短时间内大量触发同一事件,只会执行一次函数,实现原理为设置一个定时器,约定在xx毫秒后再触发事件处理,每次触发事件都会重新设置计时器,直到xx毫秒内无第二次操作。
应用场景
:
1.scroll滚动触发;
2.搜索框查询;
3.表单验证;
4.按钮提交 。
如果在这里不做防抖时,每输入一个字/滚动屏幕,都会触发事件处理,造成性能浪费。
防抖是延迟执行,而节流是间隔执行。
节流:间隔执行。每隔一段时间就执行一次,实现原理为设置一个定时器,约定xx毫秒后执行事件,如果时间到了,那么执行函数并重置定时器,和防抖的区别在于:防抖每次触发事件都重置定时器,而节流在定时器到时间后再清空定时器。
2 实现
2.1 防抖
<title>防抖</title>
<script src="./underscore.js"></script>
<style>
#container{
height: 200px;
background-color: rgb(119, 115, 110);
color: #fff;
text-align: center;
line-height: 200px;
font-size: 30px;
}
</style>
</head>
<body>
<!-- dom容器 -->
<div id="container"></div>
<script>
// 演示事件如何频繁发生
// 1.获取dom容器
let container = document.querySelector('#container');
// // 2.绑定事件,触发事件频繁发生
let count=1;
function doSomeThing(e){
console.log(this); //windows-->container
console.log(e); //undefined--->需要修改这里事件对象 让它指向mousemove
// 可能做回调或者是ajax请求
container.innerHTML= count++;
}
//一、使用_.debounce防抖
// container.onmousemove =_.debounce(doSomeThing,1000); //this-->指向当前的dom节点 事件指向事件对象mousemove
// 事件处理函数(doSomtThing)事件处理函数在一定时间后(1000)才执行
// 防抖原理:如果这段时间再次调用 则会重新计算时间 如果超出预定时间没有调用 则执行事件函数
// container-->debounce-->doSomeThing
//二、自己封装防抖函数
container.onmousemove =debounce(doSomeThing,1000);
// 现在是自己封装防抖函数
// fun形参来接收--doSomeThing wait形参来接收--1000ms 1s
function debounce(fun,wait){
let timeout;
return function(){
// console.log(this);
// console.log(arguments); //mousemove
let argus=arguments;
//此时的this指向是指向Windows 现在需要修改this指向,让this指向dom容器
let context=this;
// 时间会一直走 ---需要使用清除超时 每次在调用之前 清除之前的定时器,使用新的定时器
clearTimeout(timeout);
timeout = setTimeout(function(){
// 通过apply修改this指向
fun.apply(context,argus);// 超过等待的时间再去调用domeSomeThing
},wait)
}
}
</script>
总结:一、使用_.debounce防抖;二、自己封装防抖函数。
2.2 节流
<title>节流</title>
<script src="./undersource.js"></script>
<style>
#container{
height: 200px;
background-color: rgb(119, 115, 110);
color: #fff;
text-align: center;
line-height: 200px;
font-size: 30px;
}
</style>
</head>
<body>
<!-- dom容器 -->
<div id="container"></div>
<script>
// 演示事件如何频繁发生
// 1.获取dom容器
let container = document.querySelector('#container');
// 2.绑定事件,触发事件频繁发生
let count=1;
function doSomeThing(event){
console.log(this); //windows-->container
console.log(event); //undefined--->需要修改这里事件对象 让它指向mousemove
// 可能做回调或者是ajax请求
container.innerHTML= count++;
}
//一 、使用_.throttle来节流
// container.onmousemove =_.throttle(doSomeThing,1000);
// 节流原理:如果你持续触发事件,每隔一段时间,只执行一次事件,但不触发时,还会执行一次
// 二 、自己封装一个节流函数 -->对于封装节流又有两种方法1.时间戳 2.超时调用
container.onmousemove =throttle(doSomeThing,1000);
//1.方法一 :时间戳
// function throttle(fun,wait){
// return function(){
// // 定义一个旧的时间戳
// let old=0;
// let context=this;
// let argus=arguments;
// return function(){
// // 获取一下当前时间戳
// let now=new Date().valueOf();
// // console.log(now);
// if(now-old>wait){
// // 立即执行
// fun.apply(context,argus)
// old=now;
// }
// }
// }
// }
// 2.方法二 :超时调用
function throttle(fun,wait){
let context,argus,timeout;
return function(){
context=this;
argus=arguments;
if(!timeout){
timeout=setTimeout(()=>{
fun.apply(context,argus);
// 执行完给timeout置null
timeout=null;
},wait)
}
}
}
</script>
总结:
一 、使用 _.throttle 来节流;
二 、自己封装一个节流函数。目前对于封装节流又有两种方法:1.时间戳;2.超时调用