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());
});

控制台输出:

可以看到,有时候间隔是 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事件的监听实现

最优-scroll事件的监听实现的更多相关文章

  1. Spring Boot 事件和监听

    Application Events and Listeners 1.自定义事件和监听 1.1.定义事件 package com.cjs.boot.event; import lombok.Data; ...

  2. uniapp仿h5+fire自定义事件触发监听

    仿h5+fire自定义事件触发监听 uni-app调用 event.js 源码记录(点击查看) 1.js下载地址 [event.js](https://ext.dcloud.net.cn/plugin ...

  3. 事件的监听是由awt完成的

    学swing 之前先学awt ,因为awt 是Java实现图形界面的基础. 它能够完成编写界面的基本功能,最重要的是,事件的监听是由awt完成的. 而swing是在awt基础上提供的新的界面工具包,它 ...

  4. 深入理解Spring的容器内事件发布监听机制

    目录 1. 什么是事件监听机制 2. JDK中对事件监听机制的支持 2.1 基于JDK实现对任务执行结果的监听 3.Spring容器对事件监听机制的支持 3.1 基于Spring实现对任务执行结果的监 ...

  5. MVC框架入门准备(三)事件类 - 事件的监听和触发

    在mvc框架中可以看到事件类,实现事件的监听和触发. 举例: <?php /** * 事件类 */ class Event { // 事件绑定记录 private static $events; ...

  6. Spring Boot(六)自定义事件及监听

    事件及监听并不是SpringBoot的新功能,Spring框架早已提供了完善的事件监听机制,在Spring框架中实现事件监听的流程如下: 自定义事件,继承org.springframework.con ...

  7. 【spring源码学习】spring的事件发布监听机制源码解析

    [一]相关源代码类 (1)spring的事件发布监听机制的核心管理类:org.springframework.context.event.SimpleApplicationEventMulticast ...

  8. PIE SDK矢量数据编辑事件的监听

    1.功能简介 通过IEditEvents接口,开发者可以监听到Editor对象的相关的事件,并且做出反应.包括Editor中开始编辑.结束编辑等操作,下面对矢量数据的编辑事件的监听功能进行介绍. 2. ...

  9. PIE SDK元素事件的监听

    1功能简介 元素在操作的过程中,如添加,删除,选中等操作都需要有事件的监听,PIE SDK支持对元素操作事件的监听,下面对元素事件的监听进行介绍. 2功能实现说明 2.1.1 实现思路及原理说明 第一 ...

随机推荐

  1. ASP.NET MVC5 及 EF6 学习笔记 - (目录整理)

    个人从传统的CS应用开发(WPF)开始转向BS架构应用开发: 先是采用了最容易上手也是最容易搞不清楚状况的WebForm方式入手:到后面就直接抛弃了服务器控件的开发方式,转而采用 普通页面+Ajax+ ...

  2. PMS构造函数以及apk如何扫描

    一.PackageManagerService构造函数 1.创建data目录下面以及文件(settings的构造函数),然后再添加6个SharedUserSetting 2.开始扫描并且解析APK 3 ...

  3. 使用tinymce富文本

    1.tinymce入门参考 https://www.tiny.cloud/docs/general-configuration-guide/basic-setup/ 2.tinymce安装选项 htt ...

  4. 5.html基础标签:块级+行级元素+特殊字符+嵌套规则

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. 【练习】Java中的读文件,文件的创建,写文件

    前言 大家好,给大家带来Java中的读文件,文件的创建,写文件的概述,希望你们喜欢 读文件 public static void read(String path,String filename){ ...

  6. Linux快速目录间切换cd pushd popd

    1.   cd -     当前目录和之前所在的目录之间的切换 2.   cd + Alt . 用上次命令的最后一个目录路径 要用上上次命令的最后一个目录,就Alt+.两次就可以了 3.   push ...

  7. Tools - 源代码阅读分析工具Source Insight

    简介 https://www.sourceinsight.com/ Source Insight是一个面向项目开发的程序编辑器和代码浏览器,可以分析C/C++.C#.Java.Python等语言源代码 ...

  8. Shell - 简明Shell入门

    本文以示例和注释的方式,对Shell编程的基本知识点进行了总结和回顾,所有脚本均已做了基本的调试和验证. Shell - 简明Shell入门 01 - 第一个脚本 脚本的定义.执行方法以及echo命令 ...

  9. Testing - 软件测试知识梳理 - 探索性测试

    定义 探索性测试(Exploratory Testing)是一种自由的软件测试风格,强调测试人员同时展开测试学习,测试设计,测试执行和测试结果评估等活动,以持续优化测试工作. 其特征有:即兴发挥,快速 ...

  10. appium安装完成后运行和执行python脚本的错误合集

    1.第一个错误如下: main.js: error: argument "--app": Expected one argument. null 这个一般是appium服务端安装的 ...