在 JavaScript 程序的开发中,经常会用到一些频繁触发的 DOM 事件,如 mousemove、resize,还有不是那么常用的鼠标滚轮事件:mousewheel (在 Firefox 中,滚轮事件为 DOMMouseScroll)。
浏览器为了确保这些事件能够及时响应,触发的频率会比较高,具体的触发频率各浏览器虽然有出入,但出入不大。很多时候在需要注重性能的场景下使用这些事件会想各种办法对事件的触发频率进行优化,下面说说我的一些优化方法。
mousemove 在拖拽中的优化
拖拽( Drag )是很常见的一个功能,在浏览器还没实现原生的拖拽之前,通过 mousedown、mousemove、mouseup 3种事件类型就可以模拟出拖拽效果来,当然这里不谈如何去实现一个拖拽功能。
mousemove 事件在拖拽的应用中既要确保拖拽的流畅度,又要确保拖拽时的性能,如何保持两者的平衡呢?
可以通过设置一个计数器来去掉一半的 mousemove 事件的触发,代码如下:
03 |
elem.onmousemove = function(){ |
06 |
// 当计数器为偶数的时候不执行mousemove |
07 |
if( count % 2 === 0 ){ |
上面只是增加了很少的几行代码,通过判断计数器是否为偶数,就可以去掉一半的 mousemove 事件执行的次数,同时拖拽功能的流畅度基本不受影响。
mousemove 模拟 mouseenter 效果
最近碰到这么一个需求,需要在图片上绑定一个事件,当鼠标移动到图片上时对图片进行放大,绝大多数人的第一反应就是直接使用 mouseenter 事件来处理。但是使用 mouseenter 事件会带来误触发,尽管可以使用定时器来配合也还是会有误触发,因为图片对于 mouseenter 的触发区域是比较大的,当鼠标划过一张 200*200 尺寸的图片时,此时给 mouseenter 设置一个 500 毫秒的延时,效果可能达不到预期。对交互方式做进一步的优化,当鼠标快速划过图片时不触发事件,只有鼠标短暂的停留在图片上时才触发事件。通过对 mousemove 添加一个定时器就可以实现该效果。代码如下:
03 |
clearTimeout( timer ); |
05 |
timer = setTimeout(function(){ |
10 |
img.onmousemove = move; |
11 |
img.onmouseout = function(){ |
12 |
clearTimeout( timer ); |
鼠标频繁的移动触发的 mousemove 事件会清除掉上一次添加的定时器,只有当鼠标停留时间超过设置的 200 毫秒才会触发事件,当然在鼠标移开的时候一定要记得清除掉定时器。360图片搜索就采用了这种触发方式,这样就不会再有误触发了。
resize 事件的优化
resize 是在浏览器窗口大小改变的时候触发的事件,通常改变一次会触发 2、3 次 resize 事件,对于 IE6/7 resize 更容易被触发。resize 事件通常用于当窗口改变大小时,网页的布局也会根据窗口大小进行自适应布局。自适应布局如果对性能的消耗比较大,那么就要尤为注意 resize 触发的频率。同样使用定时器来实现。
01 |
var throttle = function( fn, timeout ){ |
08 |
clearTimeout( timer ); |
10 |
timer = setTimeout(function(){ |
11 |
fn.apply( self, args ); |
16 |
window.onresize = throttle(function(){ |
通过反复的调试,发觉给 resize 添加一个 100 毫秒的延迟的效果会比较理想,既能保证事件的及时性,又能达到优化的目的。
mousewheel 事件的优化
mousewheel 是鼠标滚轮滚动时触发的事件,在 Firefox 中该事件名为 DOMMouseScroll,在一些场合下,比如通过鼠标滚轮来控制 lightbox 组件图片的前后切换,又或者通过鼠标滚轮来放大和缩小地图。鼠标滚轮通常都会比较灵活,可能一次会滚动好几次,但是在具体的应用中这种太灵活的滚动在前面提到过的场景中必然会有误触发。直接将上面封装好的 throttle 函数拿过来稍微改下时间间隔同样能达到优化效果。
1 |
window.onmousewheel = throttle(function(){ |
鼠标滚轮设置 200 毫秒的延迟会有较理想的效果。
以上的一些优化方法大多是通过定时器来实现的,关键还是看如何灵活运用了。这些优化并不限于性能上的优化,还有交互效果上的优化,说到底就是以前端的角度出发,从细节入手来提升用户体验。
本文转自:http://stylechen.com/dom-event-optimize.html
- 前端性能优化--为什么DOM操作慢? 浅谈DOM的操作以及性能优化问题-重绘重排 为什么要减少DOM操作 为什么要减少操作DOM
前端性能优化--为什么DOM操作慢? 作为一个前端,不能不考虑性能问题.对于大多数前端来说,性能优化的方法可能包括以下这些: 减少HTTP请求(合并css.js,雪碧图/base64图片) 压缩( ...
- 转:浅谈CSS在前端优化中一些值得注意的关键点
前端优化工作中要考虑的元素多种多样,而合理地使用CSS脚本可以在很大程度上优化页面的加载性能,以下我们就来浅谈CSS在前端优化中一些值得注意的关键点: 当谈到Web的“高性能”时,很多人想到的是页面加 ...
- 浅谈DOM性能考虑
浅谈DOM性能考虑 很多人都会忽视脚本对Web应用整体性能的影响.为保证应用的流畅运行,在为文档编写和应用脚本时,需要注意一些问题.一.尽量减少访问DOM和尽量减少标记 访问DOM的方式对脚本性 ...
- Js之浅谈dom操作
JavaScript之浅谈dom操作 1.理解dom: DOM(Document Object Model ,文档对象模型)一种独立于语言,用于操作xml,html文档的应用编程接口. 怎么说,我从两 ...
- 浅谈tomcat中间件的优化【转】
今天来总结一下tomcat的一些优化的方案,由于本人才疏学浅,写的不好,勿喷! tomcat对于大多数从事开发工作的童鞋应该不会很陌生,通常做为默认的开发环境来为大家服务,不过tomcat默认的一些配 ...
- [原创]浅谈H5页面性能优化方法
[原创]浅谈H5页面性能优化方法 前阶段公司H5页面性能测试,其中测试时也发现了一些性能瓶颈问题,接下来我们在来谈谈H5页面性能优化,仅仅是一些常用H5页面性能优化措施,其实和Web页面性能优化思路大 ...
- MYSQL优化浅谈,工具及优化点介绍,mysqldumpslow,pt-query-digest,explain等
MYSQL优化浅谈 msyql是开发常用的关系型数据库,快速.稳定.开源等优点就不说了. 个人认为,项目上线,标志着一个项目真正的开始.从运维,到反馈,到再分析,再版本迭代,再优化… 这是一个漫长且考 ...
- 浅谈Unity的渲染优化(1): 性能分析和瓶颈判断(上篇)
http://www.taidous.com/article-667-1.html 前言 首先,这个系列文章做个大致的介绍,题目"浅谈Unity",因为公司和国内大部分3D手游开发 ...
- 浅谈Javascript事件模拟
事件是用来描述网页中某一特定有趣时刻的,众所周知事件通常是在由用户和浏览器进行交互时触发,其实不然,通过Javascript可以在任何时间触发特定的事件,并且这些事件与浏览器创建的事件是相同的.这就意 ...
随机推荐
- 37 Reasons why your Neural Network is not working
37 Reasons why your Neural Network is not working Neural Network Check List 如何使用这个指南 数据问题 检查输入数据 试一下 ...
- java web 下载文件 response.setHeader()的用法 (转载)
response.setHeader()的用法 response.setHeader()下载中文文件名乱码问题 收藏 1. HTTP消息头 (1)通用信息头 即能用于请求消息中,也能用于响应信息中,但 ...
- 2020-07-13:es是去查id再根据id去查数据库这种方式好,还是所有数据都放es,直接去查es好?
福哥答案2020-07-13: 有人觉得第一种方法好,也有人觉得第二种方法好.如果搜索字段远小于显示字段,比如搜索字段为3个,显示字段有20个,这个时候用第一种方法好.es+hbase,一般这样搭配. ...
- 如何将返回的JSon字符串用MAP格式读取
语法是这样: ObjectMapper mapper = new ObjectMapper(); Map resultMap=null; resultMap = mapper.readValue(in ...
- eric4 中 pyqt .py文件结尾的 代码
if __name__ == "__main__": import sys app = QtGui.QApplication(sys.argv) ui = MainWindow() ...
- JS 时间获取 (常用)
/** * 获取几天之前日期 */ daysAgo(dayNum = 0) { let myDate = new Date() let lw = new Date(myDate - 1000 * 60 ...
- Socket原理及实践(Java/C/C++)
原理 基本概念 什么是TCP/IP.UDP? 详细的可以看一下这个:学习计算机网络知识只要一篇就够了! TCP/IP(Transmission Control Protocol/Internet Pr ...
- idea工程在maven projects中显示灰色的解决办法
原文链接:https://blog.csdn.net/qq_30507287/article/details/83515461 在Mac上使用idea进行开发的过程中,一般在MavenProject中 ...
- linux,运维,部署 相关
基础 linux基础命令 linux基础 部署 docker
- 关于ACID,BASE和CAP定理的探究
前言 当我看到"根据CAP理论,由于分布式系统必须保证分区容错性,所以只能选择AP原则或者CP原则"这种结论时,我感到很疑惑: 什么是分区容错性? 为什么分布式系统必须保证分区容错 ...