防抖throttle
防抖:當(dāng)事件在短時(shí)間內(nèi)持續(xù)觸發(fā)身坐,在間隔時(shí)間內(nèi)(如1000ms)耿战,只在最后一次觸發(fā)的時(shí)候丁存,執(zhí)行目標(biāo)函數(shù)鱼喉。
就是說(shuō)肺缕,防抖不會(huì)讓函數(shù)立即執(zhí)行,而是1000ms延時(shí)內(nèi)沒(méi)有再次觸發(fā)租冠,才會(huì)執(zhí)行目標(biāo)函數(shù)
實(shí)現(xiàn):通過(guò)setTimeout做延時(shí)處理,如果定時(shí)器不為空薯嗤,則重新延時(shí)顽爹。
應(yīng)用場(chǎng)景:監(jiān)聽(tīng)輸入框keyup。
//防抖
function debounce(fn,delay){
let timer = null //借助閉包
return function() {
if(timer){
clearTimeout(timer)
}
timer = setTimeout(fn,delay) // 簡(jiǎn)化寫(xiě)法
}
}
//目標(biāo)函數(shù)
function handle(){
console.log(Math.random())
}
//監(jiān)聽(tīng)防抖
window.onscroll = debounce(handle,1000)
以上代碼的效果就是骆姐,在滾動(dòng)條停止一秒滾動(dòng)之后镜粤,才會(huì)執(zhí)行一次函數(shù),輸出一個(gè)隨機(jī)數(shù)玻褪。
節(jié)流debounce
節(jié)流:函數(shù)間隔一段時(shí)間后才能再觸發(fā)肉渴,避免某些函數(shù)觸發(fā)頻率過(guò)高。
就是說(shuō)带射,保證目標(biāo)函數(shù)在間隔時(shí)間(如1000ms)內(nèi)只執(zhí)行一次
實(shí)現(xiàn):一定時(shí)間內(nèi)只觸發(fā)一次函數(shù)同规,通過(guò)判斷是否達(dá)到一定時(shí)間來(lái)確定是否要執(zhí)行目標(biāo)函數(shù)。
應(yīng)用場(chǎng)景:防止頻繁點(diǎn)擊造成表單多次提交窟社,監(jiān)聽(tīng)滾動(dòng)事件券勺。
//節(jié)流
function throttle(fn,delay){
let valid = true
return function() {
if(!valid){
//休息時(shí)間 暫不接客
return false
}
// 工作時(shí)間,執(zhí)行函數(shù)并且在間隔期內(nèi)把狀態(tài)位設(shè)為無(wú)效
valid = false
setTimeout(() => {
fn()
valid = true;
}, delay)
}
}
//目標(biāo)函數(shù)
function handle(){
console.log(Math.random())
}
//監(jiān)聽(tīng)節(jié)流
window.onscroll = throttle(handle,1000)
以上代碼的效果就是灿里,當(dāng)滾動(dòng)條一直處于滾動(dòng)狀態(tài)時(shí)关炼,每隔一秒輸出一個(gè)隨機(jī)數(shù)。
總結(jié):(當(dāng)持續(xù)觸發(fā)時(shí))防抖讓事件只在最后一次發(fā)生匣吊。節(jié)流讓事件每隔一段時(shí)間觸發(fā)一次
然后看看vue的官方文檔里面提到的使用lodash庫(kù)來(lái)實(shí)現(xiàn)防抖的儒拂。vue在watch時(shí)使用防抖
<!-- 提供這些功能以保持精簡(jiǎn)。這也可以讓你自由選擇自己更熟悉的工具色鸳。 -->
<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
el: '#watch-example',
data: {
question: '',
answer: 'I cannot give you an answer until you ask a question!'
},
watch: {
// 如果 `question` 發(fā)生改變社痛,這個(gè)函數(shù)就會(huì)運(yùn)行
question: function (newQuestion, oldQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.debouncedGetAnswer()
}
},
created: function () {
// `_.debounce` 是一個(gè)通過(guò) Lodash 限制操作頻率的函數(shù)。
// `_.debounce` 函數(shù) (及其近親 `_.throttle`) 的知識(shí)命雀,
// 請(qǐng)參考:https://lodash.com/docs#debounce
this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
},
methods: {
getAnswer: function () {
//do something...
}
}
})
</script>
可以發(fā)現(xiàn)有了lodash這個(gè)JavaScript庫(kù)之后蒜哀,要寫(xiě)節(jié)流可防抖是非常方便的。
然后看看lodash里面關(guān)于防抖debounce和節(jié)流throttle的相關(guān)介紹吧咏雌。
防抖debounce
_.debounce(func, [wait=0], [options={}])
debounce的參數(shù)
func (Function): 要防抖動(dòng)的函數(shù)。
[wait=0] (number): 需要延遲的毫秒數(shù)校焦。
[options={}] (Object): 選項(xiàng)對(duì)象赊抖。
[options.leading=false] (boolean): 指定在延遲開(kāi)始前調(diào)用。
[options.maxWait] (number): 設(shè)置 func 允許被延遲的最大值寨典。
[options.trailing=true] (boolean): 指定在延遲結(jié)束后調(diào)用氛雪。
// 避免窗口在變動(dòng)時(shí)出現(xiàn)昂貴的計(jì)算開(kāi)銷(xiāo)。
jQuery(window).on('resize', _.debounce(calculateLayout, 150));
節(jié)流throttle
_.throttle(func, [wait=0], [options={}])
throttle的參數(shù)
func (Function): 要節(jié)流的函數(shù)耸成。
[wait=0] (number): 需要節(jié)流的毫秒报亩。
[options={}] (Object): 選項(xiàng)對(duì)象浴鸿。
[options.leading=true] (boolean): 指定調(diào)用在節(jié)流開(kāi)始前。
[options.trailing=true] (boolean): 指定調(diào)用在節(jié)流結(jié)束后弦追。
// 避免在滾動(dòng)時(shí)過(guò)分的更新定位
jQuery(window).on('scroll', _.throttle(updatePosition, 100));
我大概看了一下lodash的官方文檔岳链,很豐富耶,感覺(jué)如果用這個(gè)js庫(kù)的話可以省事又規(guī)范劲件,找時(shí)間看一哈掸哑。