// 简单的防抖动函数
function debounce(func, wait, immediate) {
// 定时器变量
var timeout;
return function() {
// 每次触发 scroll handler 时先清除定时器
clearTimeout(timeout);
// 指定 xx ms 后触发真正想进行的操作 handler
timeout = setTimeout(func, wait);
};
};
// 实际想绑定在 scroll 事件上的 handler
function realFunc(){
console.log("Success");
}
// 采用了防抖动
window.addEventListener('scroll',debounce(realFunc,500));
// 没采用防抖动
window.addEventListener('scroll',realFunc);
// 防抖动函数
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() {
// 滚动中的真正的操作
}, 250);
// 绑定监听
window.addEventListener('resize', myEfficientFn);
// 简单的节流函数
function throttle(func, wait, mustRun) {
var timeout,
startTime = new Date();
return function() {
var context = this,
args = arguments,
curTime = new Date();
clearTimeout(timeout);
// 如果达到了规定的触发时间间隔,触发 handler
if(curTime - startTime >= mustRun){
func.apply(context,args);
startTime = curTime;
// 没达到触发间隔,重新设定定时器
}else{
timeout = setTimeout(func, wait);
}
};
};
// 实际想绑定在 scroll 事件上的 handler
function realFunc(){
console.log("Success");
}
// 采用了节流函数
window.addEventListener('scroll',throttle(realFunc,500,1000));
var ticking = false; // rAF 触发锁
function onScroll(){
if(!ticking) {
requestAnimationFrame(realFunc);
ticking = true;
}
}
function realFunc(){
// do something...
console.log("Success");
ticking = false;
}
// 滚动事件监听
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:优化监听
// requestAnimationFrame()
const throttle = () => {
clearTimeout(time)
const currentTime: Date = new Date()
if (Number(currentTime) - Number(startTime) >= mustTime) {
// 规定时间内必须执行一次
handleCallBack()
startTime = currentTime
} else
time = setTimeout(() => {
// 防抖动
handleCallBack()
}, waitTime)
}
window.addEventListener('scroll', throttle)
return () => {
window.removeEventListener('scroll', throttle)
}
}, [callback, mustTime, waitTime])
//这是自己写的一个基于 防抖+节流的方式实现的滚动加载监听的自定义hook 留着后面直接复制粘贴
//但是qa在测试的时候发现在安卓系统的浏览器上会有兼容的问题 如果仅仅是使用在微信上应该问题不大
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方法根据屏幕刷新频率(例如60Hz)在屏幕渲染每一帧结束之后出发的监听效果
//避免上面setTimeout的方式监听会引发渲染回流的问题