最优-scroll事件的监听实现
1. 背景和目标
前端在监听scroll这类高频率触发事件时,常常需要一个监听函数来实现监听和回调处理。传统写法上利用setInterval或setTimeout来实现。
为了减小 CPU 开支,往往需要节流函数,但是,interval的指定依旧是个难题。interval较大,会处理不及时;较小,占用内存资源。
为了实践和解决问题,打算实现一个监听 HTML 元素滚动到底部的函数:
- 监听指定 HTML 元素的
scroll事件,并正确判断是否到底部- 正确确定确定回调间隔
- 正确使用节流函数
- 组件封装
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事件的监听实现的更多相关文章
- Spring Boot 事件和监听
Application Events and Listeners 1.自定义事件和监听 1.1.定义事件 package com.cjs.boot.event; import lombok.Data; ...
- uniapp仿h5+fire自定义事件触发监听
仿h5+fire自定义事件触发监听 uni-app调用 event.js 源码记录(点击查看) 1.js下载地址 [event.js](https://ext.dcloud.net.cn/plugin ...
- 事件的监听是由awt完成的
学swing 之前先学awt ,因为awt 是Java实现图形界面的基础. 它能够完成编写界面的基本功能,最重要的是,事件的监听是由awt完成的. 而swing是在awt基础上提供的新的界面工具包,它 ...
- 深入理解Spring的容器内事件发布监听机制
目录 1. 什么是事件监听机制 2. JDK中对事件监听机制的支持 2.1 基于JDK实现对任务执行结果的监听 3.Spring容器对事件监听机制的支持 3.1 基于Spring实现对任务执行结果的监 ...
- MVC框架入门准备(三)事件类 - 事件的监听和触发
在mvc框架中可以看到事件类,实现事件的监听和触发. 举例: <?php /** * 事件类 */ class Event { // 事件绑定记录 private static $events; ...
- Spring Boot(六)自定义事件及监听
事件及监听并不是SpringBoot的新功能,Spring框架早已提供了完善的事件监听机制,在Spring框架中实现事件监听的流程如下: 自定义事件,继承org.springframework.con ...
- 【spring源码学习】spring的事件发布监听机制源码解析
[一]相关源代码类 (1)spring的事件发布监听机制的核心管理类:org.springframework.context.event.SimpleApplicationEventMulticast ...
- PIE SDK矢量数据编辑事件的监听
1.功能简介 通过IEditEvents接口,开发者可以监听到Editor对象的相关的事件,并且做出反应.包括Editor中开始编辑.结束编辑等操作,下面对矢量数据的编辑事件的监听功能进行介绍. 2. ...
- PIE SDK元素事件的监听
1功能简介 元素在操作的过程中,如添加,删除,选中等操作都需要有事件的监听,PIE SDK支持对元素操作事件的监听,下面对元素事件的监听进行介绍. 2功能实现说明 2.1.1 实现思路及原理说明 第一 ...
随机推荐
- ScriptOJ-unique#89
一般做法 const unique = (arr) => { const result = arr.reduce((acc, iter) => { if(acc.indexOf(iter) ...
- MySQL DDL--ghost执行模板和参数
常用GHOST模板 ##================================================## mysql_ip="127.0.0.1" mysql_ ...
- 开源播放器 ijkplayer (四) :Ijkplayer切换网络时停止播放的问题处理
问题起因: 在进行ijkplayer播放器的测试时,发现ijkplayer播放器在切换网络时出现直播画面停止的问题. 问题分析: 抓取日志发现:tv.danmaku.ijk.media.player. ...
- Javascript高级编程学习笔记(9)—— 执行环境
今天主要讲一下,JS底层的一些东西,这些东西不太好举例(应该是我水平不够) 望大家多多海涵,比心心 执行环境 执行环境(执行上下文,全文使用执行环境 )是JS中最为重要的一个概念,执行环境决定了,变量 ...
- JavaScript中JSON对象和JSON字符串的相互转化
一.JSON字符串转换为JSON对象 var str = '{"name":"cxh","sex":"man",&quo ...
- JavaScript中的三种弹出框的区别与使用
JavaScript中有三种原生的弹出框,分别是alert.confirm.prompt.分别表示弹出框.确认框.信息框. 以下是示例代码: <!DOCTYPE html> <htm ...
- [WINForm]C#应用程序图标设置问题
在屏幕分辨率大小不一的情况下,应用程序的图标有些电脑显示合适,有些电脑显示在图标中间出现过多空白边距: 处理方式: 1.在vs中打开ico图片 2.在图标空白处右键添加新图像类型 3.选择自己需要的尺 ...
- Vue2.0+组件库总结
转自:https://blog.csdn.net/lishanleilixin/article/details/84025459 UI组件 element - 饿了么出品的Vue2的web UI工具套 ...
- Anaconda3下安装Anaconda2
一.下载软件 下载Anaconda Python3.6版本和Anaconda Python2.7版本.下载地址:https://www.anaconda.com/download/ 下载需要FQ,也可 ...
- Beautiful Soup的用法
BEAUTIFUL SOUP的介绍 就是一个非常好用.漂亮.牛逼的第三方库,是用Python写的一个HTML/XML的解析器,它可以很好的处理不规范标记并生成剖析树(parse tree). 它提供简 ...