// 簡(jiǎn)單的防抖動(dòng)函數(shù)
function debounce(func, wait, immediate) {
// 定時(shí)器變量
var timeout;
return function() {
// 每次觸發(fā) scroll handler 時(shí)先清除定時(shí)器
clearTimeout(timeout);
// 指定 xx ms 后觸發(fā)真正想進(jìn)行的操作 handler
timeout = setTimeout(func, wait);
};
};
// 實(shí)際想綁定在 scroll 事件上的 handler
function realFunc(){
console.log("Success");
}
// 采用了防抖動(dòng)
window.addEventListener('scroll',debounce(realFunc,500));
// 沒采用防抖動(dòng)
window.addEventListener('scroll',realFunc);
// 防抖動(dòng)函數(shù)
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate & !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
var myEfficientFn = debounce(function() {
// 滾動(dòng)中的真正的操作
}, 250);
// 綁定監(jiān)聽
window.addEventListener('resize', myEfficientFn);
// 簡(jiǎn)單的節(jié)流函數(shù)
function throttle(func, wait, mustRun) {
var timeout,
startTime = new Date();
return function() {
var context = this,
args = arguments,
curTime = new Date();
clearTimeout(timeout);
// 如果達(dá)到了規(guī)定的觸發(fā)時(shí)間間隔盹舞,觸發(fā) handler
if(curTime - startTime >= mustRun){
func.apply(context,args);
startTime = curTime;
// 沒達(dá)到觸發(fā)間隔弦追,重新設(shè)定定時(shí)器
}else{
timeout = setTimeout(func, wait);
}
};
};
// 實(shí)際想綁定在 scroll 事件上的 handler
function realFunc(){
console.log("Success");
}
// 采用了節(jié)流函數(shù)
window.addEventListener('scroll',throttle(realFunc,500,1000));
var ticking = false; // rAF 觸發(fā)鎖
function onScroll(){
if(!ticking) {
requestAnimationFrame(realFunc);
ticking = true;
}
}
function realFunc(){
// do something...
console.log("Success");
ticking = false;
}
// 滾動(dòng)事件監(jiān)聽
window.addEventListener('scroll', onScroll, false);
//rAF:16.7ms
原文來自http://mp.weixin.qq.com/s/LgwTCzBgYWBe2JFXg8YMtQ
2019.11.20更新
廢話不多說直接上代碼
useEffect(() => {
let time: NodeJS.Timeout
let startTime: Date = new Date()
const handleCallBack = () => {
const { scrollY } = window
const { clientHeight, scrollHeight } = document.documentElement
if (clientHeight + scrollY >= scrollHeight - 60) {
callback()
}
}
// TODO:優(yōu)化監(jiān)聽
// requestAnimationFrame()
const throttle = () => {
clearTimeout(time)
const currentTime: Date = new Date()
if (Number(currentTime) - Number(startTime) >= mustTime) {
// 規(guī)定時(shí)間內(nèi)必須執(zhí)行一次
handleCallBack()
startTime = currentTime
} else
time = setTimeout(() => {
// 防抖動(dòng)
handleCallBack()
}, waitTime)
}
window.addEventListener('scroll', throttle)
return () => {
window.removeEventListener('scroll', throttle)
}
}, [callback, mustTime, waitTime])
//這是自己寫的一個(gè)基于 防抖+節(jié)流的方式實(shí)現(xiàn)的滾動(dòng)加載監(jiān)聽的自定義hook 留著后面直接復(fù)制粘貼
//但是qa在測(cè)試的時(shí)候發(fā)現(xiàn)在安卓系統(tǒng)的瀏覽器上會(huì)有兼容的問題 如果僅僅是使用在微信上應(yīng)該問題不大
useEffect(() => {
let doing = false;
const handleCallBack = () => {
const { scrollY } = window
const { clientHeight, scrollHeight } = document.documentElement || document.body
if (clientHeight + scrollY >= scrollHeight - 60) {
callback()
}
doing = false
}
const rafCallback = () => {
if (doing) return
doing = true
window.requestAnimationFrame(handleCallBack)
}
window.addEventListener('scroll', rafCallback)
return () => {
window.removeEventListener('scroll', rafCallback)
}
}, [callback])
//這是使用requestAnimationFrame方法根據(jù)屏幕刷新頻率(例如60Hz)在屏幕渲染每一幀結(jié)束之后出發(fā)的監(jiān)聽效果
//避免上面setTimeout的方式監(jiān)聽會(huì)引發(fā)渲染回流的問題