一、一种现象
有一个input框,每次输入都要触发一次change事件,其实这大可不必,比如我输入 “上海” 两个字,竟然触发了9次。
-
<body>
-
<input type="text" />
-
<script src="./t.js">
</script>
-
</body>
-
const input =
document.
querySelector(
'input')
-
input.
oninput =
function(
) {
-
console.
log(
this.
value)
-
}
假如每次change都会和后端发生一次交互,这个性能就会很惨。
怎么才能让这个次数变的少?
二、防抖
用户触发事件过于频繁,只要最后一次事件的操作。比如我们可以设置500ms,只要在500ms内你一直还在输入,也就是说你的停顿是少于500ms的,那么就不触发change事件里的复杂逻辑。在执行复杂逻辑之前就把定时器清理掉。
-
const input =
document.
querySelector(
'input')
-
let t =
null
-
input.
oninput =
function(
) {
-
if (t !==
null) {
-
clearTimeout(t)
-
}
-
t =
setTimeout(
() => {
-
// 用一句打印代替复杂的业务逻辑
-
console.
log(
this.
value)
-
},
500)
-
}
三、代码改进
上面的代码有2个大毛病:
- let t是个全局变量;
- 防抖的逻辑 if (t !== null) 和 业务逻辑都混在一起了。
用闭包来改进这段代码
上面,在调用debounce的时候,第一个参数是传递一个函数,
我们传的是一个() => {console.log(this.value)} ,这里的this是window,但是我们想要的是input。
所以,可以用call的方式来
-
const input =
document.
querySelector(
'input')
-
input.
oninput =
debounce(
function(
) {
// 这里如果用箭头函数,还是指向window,不能用箭头函数
-
// 业务逻辑,用一个打印代替
-
console.
log(
this.
value)
-
},
500)
-
-
function
debounce(
fn, delay) {
-
let t =
null
-
return
function(
) {
-
if (t !==
null) {
-
clearTimeout(t)
-
}
-
t =
setTimeout(
() => {
-
// 执行业务逻辑,这里的this就是input 事件对象
-
console.
log(
'this: ',
this)
-
fn.
call(
this)
-
}, delay)
-
}
-
}
四、节流
有一种情形,滚动事件,会执行很多次。
-
window.
onscroll =
function(
) {
-
console.
log(
'---------')
-
}
你看,不到一秒钟随便滚动一下就是100多次。
防抖:只执行最后一次;
节流:控制执行次数;让耗性能的方法减少执行次数;
和防抖是一样的写法
-
window.
onscroll =
throttle(
() => {
-
// 这里是业务逻辑,this:window
-
console.
log(
'..........')
-
},
500)
-
-
function
throttle(
fn, delay) {
-
let flag =
true
-
return
function(
) {
-
if (flag) {
-
setTimeout(
() => {
-
fn.
call(
this)
-
flag =
true
-
}, delay)
-
}
-
flag =
false
-
}
-
}
转载:https://blog.csdn.net/GY_U_YG/article/details/125492220
查看评论