最优-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 实现思路及原理说明 第一 ...
随机推荐
- Codeforces Round #512 E - Vasya and Good Sequences
有时候觉得自己就是个思路搬运机,只会搬运思路 这个题首先说了求的是好区间的个数, 好区间满足条件: 1.二进制位1的数量和为偶数 2.w[i]表示a[i]的二进制上1的个数 ,sum[i] = ...
- Python之旅Day3 文件操作 函数(递归|匿名|嵌套|高阶)函数式编程 内置方法
知识回顾 常见五大数据类型分类小结:数字.字符串.列表.元组.字典 按存值个数区分:容器类型(列表.字典.元组) 标量原子(数字.字符串) 按是否可变区分:可变(列表.字典) 不可变(数字.字符串.元 ...
- 项目Alpha冲刺(团队5/10)
项目Alpha冲刺(团队5/10) 团队名称: 云打印 作业要求: 项目Alpha冲刺(团队) 作业目标: 完成项目Alpha版本 团队队员 队员学号 队员姓名 个人博客地址 备注 221600412 ...
- html canvas 的宽高以及像素限制
canvas 宽高设置不合适的话,是画不出东西出来的 https://stackoverflow.com/questions/6081483/maximum-size-of-a-canvas-elem ...
- Spring AOP术语:连接点和切点的区别。
定义: 1.连接点(Join point):连接点是在应用执行过程中能够插入切面(Aspect)的一个点.这些点可以是调用方法时.甚至修改一个字段时. 2.切点(Pointcut):切点是指通知(Ad ...
- 《Opencv 3 计算机视觉 python语言实现》· 第二遍 —— 读后笔记
概览 代码实战 https://github.com/xinghalo/ml-in-action/tree/master/book-opencv
- 第六节:详细讲解Java中的装箱与拆箱及其字符串
前言 大家好,给大家带来详细讲解Java中的装箱与拆箱及其字符串的概述,希望你们喜欢 装箱与拆箱 封装类有:Byte , short , Integer , Character , long , Fl ...
- spring框架学习笔记7:事务管理及案例
Spring提供了一套管理项目中的事务的机制 以前写过一篇简单的介绍事务的随笔:http://www.cnblogs.com/xuyiqing/p/8430214.html 还有一篇Hibernate ...
- ElasticSearch权威指南学习(分布式集群)
空集群 只有一个空节点的集群 一个节点(node)就是一个Elasticsearch实例,而一个集群(cluster)由一个或多个节点组成,它们具有相同的cluster.name,它们协同工作,分享数 ...
- Shell-9--条件测试