節(jié)流
節(jié)流:如果你持續(xù)觸發(fā)事件,每隔一段時間缕溉,只執(zhí)行一次事件
關(guān)于節(jié)流的實現(xiàn)待牵,有兩種主流的實現(xiàn)方式,一種是使用時間戳的方式唧瘾,一種是設(shè)置定時器
使用時間戳
實現(xiàn)思路為:當觸發(fā)條件的時候措译,我們?nèi)〕霎斍暗臅r間戳,然后減去之前的時間戳(初始化為0)饰序,如果大于設(shè)定的時間周期领虹,就執(zhí)行函數(shù),然后更新時間戳為當前的時間戳求豫,如果小于塌衰,則不執(zhí)行
function throttle(func, wait) {
var context, args
var previous = 0
return function() {
var now = +new Date()
context = this
args = arguments
if(now - previous > wait) {
func.apply(context, args)
previous = now
}
}
}
使用定時器
實現(xiàn)思路為:當觸發(fā)事件的時候,我們設(shè)置一個定時器蝠嘉,再次觸發(fā)事件的時候最疆,如果定時器存在,就不執(zhí)行蚤告,直到定時器執(zhí)行努酸,然后執(zhí)行函數(shù),清空定時器杜恰,再設(shè)置下一個定時器
function throttle(func, wait) {
var timeout
var context, args
return function() {
context = this
args = arguments
if(!timeout) {
timeout = setTimeout(function() {
timeout = null
func.apply(context, args)
}, wait)
}
}
}
比較兩種方法:
- 第一種事件會立即執(zhí)行蚊逢,第二種事件會在n秒后第一次執(zhí)行
- 第一種事件停止觸發(fā)后沒有辦法再執(zhí)行事件,第二種事件停止觸發(fā)后依然會再執(zhí)行一次事件
雙劍合璧
鼠標移入能立即執(zhí)行箫章,停止觸發(fā)的時候還能再執(zhí)行一次
function throttle(func, wait) {
var timeout, context, args, reslut
var previous = 0
var later = function() {
previous = +new Date()
timeout = null
func.apply(context, args)
}
var throttled = function() {
var now = +new Date()
// 下次觸發(fā)func剩余時間
var remaining = wait - (now - previous)
context = this
args = arguments
// 如果沒有剩余時間了或者你改了系統(tǒng)時間
if(remaining <=0 || remaining > wait) {
if(timeout) {
clearTimeout(timeout)
timeout = null
}
previous = now
func.apply(context, args)
} else if(!timeout) {
timeout = setTimeout(later, remaining)
}
}
return throttled
}
優(yōu)化
我們可增加一個參數(shù)options來約定:
- leading:false表示禁用第一次執(zhí)行
- trailing:false表示禁用停止觸發(fā)的回調(diào)
function throttle(func, wait, options) {
var timeout, context, args, reslut
var previous = 0
if(!options) options = {}
var later = function() {
previous = options.leading === false ? 0 : new Date().getTime()
timeout = null
func.apply(context, args)
if(!timeout) context = args = null
}
var throttled = function() {
var now = new Date().getTime()
if(!previous && options.leading === false) previous = now
// 下次觸發(fā)func剩余時間
var remaining = wait - (now - previous)
context = this
args = arguments
// 如果沒有剩余時間了或者你改了系統(tǒng)時間
if(remaining <=0 || remaining > wait) {
if(timeout) {
clearTimeout(timeout)
timeout = null
}
previous = now
func.apply(context, args)
if(!timeout) context = args = null
} else if(!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining)
}
}
// 取消功能
throttled.cancel = function() {
clearTimeout(timeout)
previous = 0
timeout = null
}
return throttled
}
注意
如果同時設(shè)置 leading:false和trailing:false,比如當你鼠標移出的時候镜会,因為trailing設(shè)置為false檬寂,停止觸發(fā)的時候不會設(shè)置定時器,所以只要再過了設(shè)置的時間戳表,再移入的話桶至,就會立即執(zhí)行,就違反了leading:false匾旭,所以throttle只有三種用法:
throttle(func, 1000)
throttle(func, 1000, {leading:false})
throttle(func, 1000, {trailing:false})