zoukankan      html  css  js  c++  java
  • 最优-scroll事件的监听实现

    1. 背景和目标

    前端在监听scroll这类高频率触发事件时,常常需要一个监听函数来实现监听和回调处理。传统写法上利用setIntervalsetTimeout来实现。

    为了减小 CPU 开支,往往需要节流函数,但是,interval的指定依旧是个难题。interval较大,会处理不及时;较小,占用内存资源。

    为了实践和解决问题,打算实现一个监听 HTML 元素滚动到底部的函数

    1. 监听指定 HTML 元素的scroll事件,并正确判断是否到底部
    2. 正确确定确定回调间隔
    3. 正确使用节流函数
    4. 组件封装

    2. window.requestAnimationFrame()

    前文说到,如果利用setTimeout或者setInterval,回调间隔interval很难确定。最理想的情况就是:回调间隔等于显示屏(浏览器)刷新频率。

    浏览器刷新频率一般会略低于显示屏刷新频率,为16.7次/ms。具体说,就是:scroll事件每次触发时候的时间间隔。通过代码来看一下:

    var app = document.getElementById("app");
    app.addEventListener("scroll", function() {
      console.log(new Date().getTime());
    });
    

    控制台输出:
    1.png

    可以看到,有时候间隔是 10ms,有时候是 30ms,如果我们自己来设定interval,应该取最小值。然而,不同浏览器和不同电脑的刷新频率不确定。如果设置过小,还会造成刷新频率低的显示屏的 CPU 损耗。

    所以,使用window.requestAnimationFrame()来让浏览器根据刷新频率自动设置interval。我们只需要关注回调函数即可。

    当然,这个函数本身还实现了很多优化,可以点我看一下

    3. 节流函数

    由于window.requestAnimationFrame()的特效,所以它可以在同一帧中被重复绘制。这时候,就需要节流函数,保证requestAnimationFrame的回调队列中只有一个函数在执行

    // 节流函数 : 减少浏览器内存消耗
    function throttle(ele, callback) {
      var isRunning = false;
      return function() {
        if (isRunning) return;
        isRunning = true;
        // requestAnimationFrame:回调间隔 = 浏览器重绘频率
        window.requestAnimationFrame(function(timestamp) {
          if (ele.scrollTop + ele.clientHeight >= ele.scrollHeight) {
            // 检测是否滚动到元素底部
            callback();
          }
          isRunning = false;
        });
      };
    }
    

    4. 代码封装

    函数封装详见script.js,调用样例详见index.html

    基于上面,我们封装script.js

    // 节流函数 : 减少浏览器内存消耗
    function throttle(ele, callback) {
      var isRunning = false;
      return function() {
        if (isRunning) return;
        isRunning = true;
        // requestAnimationFrame:回调间隔 = 浏览器重绘频率
        window.requestAnimationFrame(function(timestamp) {
          if (ele.scrollTop + ele.clientHeight >= ele.scrollHeight) {
            // 检测是否滚动到元素底部
            callback();
          }
          isRunning = false;
        });
      };
    }
    
    /**
     * 监听HTML元素是否滚动到底部 : 兼容ES5
     * @param {object} ele HTML元素
     * @param {function} callback 滚动到底部后的回调函数
     */
    function listenScrollToBottom(ele, callback) {
      if (ele === null || ele === undefined) {
        // 节点不存在:抛出错误
        throw new Error("Undefined COM");
        return;
      }
      ele.addEventListener("scroll", throttle(ele, callback), false); // 监听 scroll 事件
    }
    

    将需要监听的 HTML 元素和回调函数传入,即可在 HTML 元素滚动到底部时,触发相应的操作。例如:瀑布流、缓冲加载等。下面是控制台输出一段文字。

    <body>
      <div id="app">
        <div class="inner"></div>
      </div>
      <script>
        var app = document.getElementById('app')
        listenScrollToBottom(app , function() { // 回调函数
          console.log("Scroll to bottom")
        })
      </script>
    </body>
    

    4. 关于

    欢迎技术交流,引用请注明出处。
    个人网站:董沅鑫的个人网站
    原文链接:最优-scroll事件的监听实现

  • 相关阅读:
    CS229 6.4 Neurons Networks Autoencoders and Sparsity
    CS229 6.3 Neurons Networks Gradient Checking
    【Leetcode】【Easy】Min Stack
    【Leetcode】【Easy】Merge Sorted Array
    【Leetcode】【Easy】ZigZag Conversion
    【Leetcode】【Easy】Valid Palindrome
    【Leetcode】【Easy】Reverse Integer
    【Leetcode】【Easy】Palindrome Number
    【Leetcode】【Easy】Length of Last Word
    【Leetcode】【Easy】Remove Nth Node From End of List
  • 原文地址:https://www.cnblogs.com/geyouneihan/p/9377259.html
Copyright © 2011-2022 走看看