什么是防抖和节流,他们的应用场景有哪些
Sonder
2020-03-20
3907字
10分钟
浏览 (3.3k)
节流(throttle):固定时间内事件只执行一次
在固定时间内事件只执行一次。应用场景:高频的监听事件、滚动事件、input 框实时搜索并发送请求展示下拉列表,每隔一秒发送一次请求 (也可做防抖)
节流可以比作过红绿灯,每等一个红灯时间就可以过一批
代码如下,可以看出来节流重在加锁 timer=timeout
<html>
<head>
<title>节流</title>
</head>
<body>
<button onclick="clickBtn1()">使用时间戳</button>
<button onclick="clickBtn2()">使用定时器</button>
<script type="text/javascript">
let clickBtn1 = throttle1(function(){
console.log("使用时间戳;无论你高频点多少次都会在n秒内执行一次,节流会稀释函数的执行频率")
});
let clickBtn2 = throttle2(function(){
console.log(12312)
});
//高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率
//使用时间戳
function throttle1(fn,wait = 300) {
let time = 0;
return function(){
let _this = this;
let args = arguments;
let now = Date.now();
if(now - time > wait) {
fn.apply(_this,args);
time = now;
}
}
}
// 使用定时器
function throttle2(fn,wait = 300) {
let timer;
return function(){
let _this = this;
let args = arguments;
if(!timer) {
timer = setTimeout(function(){
timer = null;
fn.apply(_this,args);
},wait);
}
}
}
</script>
</body>
</html>
防抖(debounce):最后一个人说了算
多次事件只执行最后一次。应用场景:登录、发短信,调整浏览器窗口大小,文本编辑器实时保存,输入框输入事件,鼠标移动
防抖可以比作等电梯,只要有一个人进来,就需要再等一会儿。业务场景有避免登录按钮多次点击的重复提交。
代码如下,可以看出来防抖重在清零 clearTimeout(timer)
<html>
<head>
<title>防抖</title>
</head>
<body>
<button onclick="clickBtn(1)">按钮</button>
<script type="text/javascript">
let clickBtn = debounce(function(i){
console.log("触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间")
});
//防抖,触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
function debounce(fn,wait = 300) {
let timer;
return function(){
let _this = this;
let args = arguments; // 是一个对应于传递给函数的参数的类数组对象
if(timer) { clearTimeout(timer) }
timer = setTimeout(function(){
fn.apply(_this,args);
},wait);
}
}
// 拉扯你的浏览器窗口
// window.onresize = debounce(function(){
// console.log("resize")
// });
</script>
</body>
</html>
Vue事件中使用方法
/**
* utils/index.js
* 节流
* @param fn
* @param wait
* @returns {(function(): void)|*}
*/
export function throttle(fn,wait = 300) {
let time = 0;
return function(){
let _this = this;
let args = arguments;
let now = Date.now();
if(now - time > wait) {
fn.apply(_this,args);
time = now;
}
}
}
import {throttle} from "@/utils"
methods: {
Send:throttle(function(id,name){
// ...code
})
}
不使用导入
function debounce(fn,wait = 500) {
let timer;
return function(){
let _this = this;
let args = arguments; // 是一个对应于传递给函数的参数的类数组对象
if(timer) { clearTimeout(timer) }
timer = setTimeout(function(){
fn.apply(_this,args);
},wait);
}
}
export default {
methods: {
loadData() {
this.getData(this)
}
getData: debounce(that => {
that.limit += 10;
}
}
如果是点击事件的话
<button @click="getArticleOrder(item)">点击</button>
methods: {
// 解决获取不到this的问题
//Duplicate keys detected: 'orderIndex'. This may cause an update error.
setArticleOrder: debounce(function (...args) {
this.getArticleOrderDebounce(...args)
}),
setArticleOrderDebounce(order) {
if (order === this.orderIndex) return
this.orderIndex = order
}
}