作者:薄荷前端
連接:https://juejin.im/post/6844903669389885453
來源:掘金
<div class="box">
<label for="none">
啥都沒有: <input type="text" id="none">
</label>
</div>
// 每次keyup及調用foo
function foo(content) {
console.log('調用: ' + content)
}
let inputNone = document.getElementById('none')
inputNone.addEventListener('keyup', function (e) {
foo(e.target.value)
})
動畫網址:
https://github.com/s95050937/IT30/blob/master/%E5%9C%96%E7%89%87%E5%8D%80/D09/01.gif
可以發現非常浪費資源而且消耗性能
在事件被觸發n秒後再執行回調,如果n秒內又被觸發則重新計時
<div class="box">
<label for="debounce">
防抖後: <input type="text" id="debounce">
</label>
</div>
// 函數本體
function foo(content) {
console.log('調用: ' + content)
}
function debounce(fun, delay) {
return function (args) {
let that = this
let _args = args
// 每次執行的時候重置setTimeout
clearTimeout(fun.time)
fun.time = setTimeout(function () {
// 執行傳入的fun1(透過call方法傳遞參數_args)
fun.call(that, _args)
}, delay)
}
}
let inputDebounce = document.getElementById('debounce')
let debounceFoo = debounce(foo, 500)
inputDebounce.addEventListener('keyup', function (e) {
debounceFoo(e.target.value)
})
動畫網址:
https://github.com/s95050937/IT30/blob/master/%E5%9C%96%E7%89%87%E5%8D%80/D09/02.gif
<div class="box">
<label for="throttle">
節流後: <input type="text" id="throttle">
</label>
</div>
function throttle(fun, delay) {
let last, deferTimer
return function (args) {
let that = this
let _args = args
let now = +new Date()
// 1. 如果last不存在代表第一次執行函數,所以可以直接執行函數
// 2. 如果now小於 last + delay表示上一次執行函數的時間已經超過delay的時間
// 所以可以直接執行函數(else代碼塊)
if (last && now < last + delay) {
// 底下確保不會發生
// 最後執行代碼的時候,因為刷新last,造成不會執行最後的結果
clearTimeout(deferTimer)
deferTimer = setTimeout(function () {
last = now
fun.call(that, _args)
}, delay)
} else {
last = now
fun.call(that, _args)
}
}
}
let throttleAjax = throttle(ajax, 1000)
let inputc = document.getElementById('throttle')
inputc.addEventListener('keyup', function(e) {
throttleAjax(e.target.value)
})
動畫網址:
https://github.com/s95050937/IT30/blob/master/%E5%9C%96%E7%89%87%E5%8D%80/D09/03.gif
可能有人會對以下代碼不知道為啥,其實直接把他註解掉就很明顯
if (last && now < last + delay) {
// 底下確保不會發生
// 最後執行代碼的時候,因為刷新last,造成不會執行最後的結果
clearTimeout(deferTimer)
deferTimer = setTimeout(function () {
last = now
fun.call(that, _args)
}, delay)
}
新的:
function throttle(fun, delay) {
let last, deferTimer
return function (args) {
let that = this
let _args = args
let now = +new Date()
// 裡面被註解
if (last && now < last + delay) {
// clearTimeout(deferTimer)
// deferTimer = setTimeout(function () {
// last = now
// fun.call(that, _args)
// }, delay)
} else {
last = now
fun.call(that, _args)
}
}
}
let throttleFoo = throttle(ajax, 1000)
let inputThrottle = document.getElementById('throttle')
inputThrottle.addEventListener('keyup', function (e) {
throttleFoo(e.target.value)
})
動畫網址:
https://github.com/s95050937/IT30/blob/master/%E5%9C%96%E7%89%87%E5%8D%80/D09/04.gif
有沒有注意到一個最關鍵的點,雖然最後並不會執行打印 aaaaaaaaaaa
因為打印完aaaaaaaa,我們的時長還不到一秒因此進入到 if 迴圈裡面啥都沒做
if (last && now < last + delay) { // clearTimeout(deferTimer) // deferTimer = setTimeout(function () { // last = now // fun.call(that, _args) // }, delay) }