高性能Scroll

// 簡單的防抖動函數(shù)
function debounce(func, wait, immediate) {
    // 定時器變量
    var timeout;
    return function() {
        // 每次觸發(fā) scroll handler 時先清除定時器
        clearTimeout(timeout);
        // 指定 xx ms 后觸發(fā)真正想進行的操作 handler
        timeout = setTimeout(func, wait);
    };
};
 
// 實際想綁定在 scroll 事件上的 handler
function realFunc(){
    console.log("Success");
}
 
// 采用了防抖動
window.addEventListener('scroll',debounce(realFunc,500));
// 沒采用防抖動
window.addEventListener('scroll',realFunc);
// 防抖動函數(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() {
    // 滾動中的真正的操作
}, 250);
 
// 綁定監(jiān)聽
window.addEventListener('resize', myEfficientFn);
// 簡單的節(jié)流函數(shù)
function throttle(func, wait, mustRun) {
    var timeout,
        startTime = new Date();

    return function() {
        var context = this,
            args = arguments,
            curTime = new Date();

        clearTimeout(timeout);
        // 如果達到了規(guī)定的觸發(fā)時間間隔,觸發(fā) handler
        if(curTime - startTime >= mustRun){
            func.apply(context,args);
            startTime = curTime;
        // 沒達到觸發(fā)間隔,重新設(shè)定定時器
        }else{
            timeout = setTimeout(func, wait);
        }
    };
};
// 實際想綁定在 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;
}
// 滾動事件監(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ī)定時間內(nèi)必須執(zhí)行一次
        handleCallBack()
        startTime = currentTime
      } else
        time = setTimeout(() => {
          // 防抖動
          handleCallBack()
        }, waitTime)
    }

    window.addEventListener('scroll', throttle)
    return () => {
      window.removeEventListener('scroll', throttle)
    }
  }, [callback, mustTime, waitTime])
//這是自己寫的一個基于 防抖+節(jié)流的方式實現(xiàn)的滾動加載監(jiān)聽的自定義hook 留著后面直接復(fù)制粘貼
//但是qa在測試的時候發(fā)現(xiàn)在安卓系統(tǒng)的瀏覽器上會有兼容的問題 如果僅僅是使用在微信上應(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)聽會引發(fā)渲染回流的問題
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容