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. jsp页面有一个注册form表单,传值的时候后台接收到的全部是null

    [页面上的传值元素一定要有name属性才可在后台接受到参数的值.切记!] 此处一定要注意,form表单里面的元素,比如input元素是否和后台的requset.getparameter();中的参数名 ...

  2. 桌面管理工具 RedisDesktopManager 0.8.8

    RedisDesktopManager 0.8.8  发布,此版本更新内容如下: 改进: Show key bytes length and value bytes length #3677 修复: ...

  3. PHP查看内存使用

    第一想法:memory_get_usage() 用microtime函数就可以分析程序执行时间memory_get_usage可以分析内存占用空间 SQL的效率可以使用打开慢查询查看日志分析SQL 找 ...

  4. redis之一初识redis

    本文主要围绕以下几点进行阐述: 1.什么是redis? 2.为什么要使用redis呢? 3.redis的一些基本配置 4.redis的缺点? 正文: 1.什么是redis? Redis是一款内存高速缓 ...

  5. 如何修改config?

    这几天在做给WCF做加密传输,结果当然是实现了加密传输,同时也发现了一个问题,有没有大神来答疑解惑一下. 事情是这样的. 在客户端的配置中,需要加入一个behavior,在config文件中是这样的. ...

  6. 6. ASP.NET MVC 5.0 中的HTML Helper【HTML 帮助类】

    这篇文章,我将带领大家学习HTML Helper.[PS:上一篇-->5.ASP.NET MVC 中的Area[区域]是什么] HTML Helpers是用来创建HTML标签进而创建HTML控件 ...

  7. LeetCode--No.002 Add Two Numbers

    Add Two Numbers Total Accepted: 160702 Total Submissions: 664770 Difficulty: Medium You are given tw ...

  8. 课程四(Convolutional Neural Networks),第二 周(Deep convolutional models: case studies) —— 0.Learning Goals

    Learning Goals Understand multiple foundational papers of convolutional neural networks Analyze the ...

  9. 《ASP.NET Core跨平台开发从入门到实战》Web API自定义格式化protobuf

    <ASP.NET Core跨平台开发从入门到实战>样章节 Web API自定义格式化protobuf. 样章 Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于 ...

  10. 服务端如何安全获取客户端请求IP地址

    服务端如何获取客户端请求IP地址,网上代码一搜一大把.其中比较常见有x-forwarded-for.client-ip等请求头,及remote_addr参数,那么为什么会存在这么多获取方式,以及到底怎 ...