在 JavaScript 程序的开发中,经常会用到一些频繁触发的 DOM 事件,如 mousemove、resize,还有不是那么常用的鼠标滚轮事件:mousewheel (在 Firefox 中,滚轮事件为 DOMMouseScroll)。

浏览器为了确保这些事件能够及时响应,触发的频率会比较高,具体的触发频率各浏览器虽然有出入,但出入不大。很多时候在需要注重性能的场景下使用这些事件会想各种办法对事件的触发频率进行优化,下面说说我的一些优化方法。

mousemove 在拖拽中的优化

拖拽( Drag )是很常见的一个功能,在浏览器还没实现原生的拖拽之前,通过 mousedown、mousemove、mouseup 3种事件类型就可以模拟出拖拽效果来,当然这里不谈如何去实现一个拖拽功能。

mousemove 事件在拖拽的应用中既要确保拖拽的流畅度,又要确保拖拽时的性能,如何保持两者的平衡呢?

可以通过设置一个计数器来去掉一半的 mousemove 事件的触发,代码如下:

01 var count = 0;
02  
03 elem.onmousemove = function(){
04     count++;
05      
06     // 当计数器为偶数的时候不执行mousemove
07     if( count % 2 === 0 ){
08         return;
09     }
10      
11     // 实现拖拽功能的代码...
12 };

上面只是增加了很少的几行代码,通过判断计数器是否为偶数,就可以去掉一半的 mousemove 事件执行的次数,同时拖拽功能的流畅度基本不受影响。

mousemove 模拟 mouseenter 效果

最近碰到这么一个需求,需要在图片上绑定一个事件,当鼠标移动到图片上时对图片进行放大,绝大多数人的第一反应就是直接使用 mouseenter 事件来处理。但是使用 mouseenter 事件会带来误触发,尽管可以使用定时器来配合也还是会有误触发,因为图片对于 mouseenter 的触发区域是比较大的,当鼠标划过一张 200*200 尺寸的图片时,此时给 mouseenter 设置一个 500 毫秒的延时,效果可能达不到预期。对交互方式做进一步的优化,当鼠标快速划过图片时不触发事件,只有鼠标短暂的停留在图片上时才触发事件。通过对 mousemove 添加一个定时器就可以实现该效果。代码如下:

01 var timer,
02     move = function(){
03         clearTimeout( timer );
04         // 设置一个较短的定时器
05         timer = setTimeout(function(){
06             // 这里是实现图片放大的代码...
07         }, 200 );
08     };
09      
10 img.onmousemove = move;
11 img.onmouseout = function(){
12     clearTimeout( timer );
13 };

鼠标频繁的移动触发的 mousemove 事件会清除掉上一次添加的定时器,只有当鼠标停留时间超过设置的 200 毫秒才会触发事件,当然在鼠标移开的时候一定要记得清除掉定时器。360图片搜索就采用了这种触发方式,这样就不会再有误触发了。

resize 事件的优化

resize 是在浏览器窗口大小改变的时候触发的事件,通常改变一次会触发 2、3 次 resize 事件,对于 IE6/7 resize 更容易被触发。resize 事件通常用于当窗口改变大小时,网页的布局也会根据窗口大小进行自适应布局。自适应布局如果对性能的消耗比较大,那么就要尤为注意 resize 触发的频率。同样使用定时器来实现。

01 var throttle = function( fn, timeout ){       
02     var timer;
03      
04     return function(){
05         var self = this,
06             args = arguments;
07  
08         clearTimeout( timer );
09  
10         timer = setTimeout(function(){
11             fn.apply( self, args );
12         }, timeout );
13     };
14 };
15  
16 window.onresize = throttle(function(){
17     // 自适应布局的代码...
18 }, 100 );

通过反复的调试,发觉给 resize 添加一个 100 毫秒的延迟的效果会比较理想,既能保证事件的及时性,又能达到优化的目的。

mousewheel 事件的优化

mousewheel 是鼠标滚轮滚动时触发的事件,在 Firefox 中该事件名为 DOMMouseScroll,在一些场合下,比如通过鼠标滚轮来控制 lightbox 组件图片的前后切换,又或者通过鼠标滚轮来放大和缩小地图。鼠标滚轮通常都会比较灵活,可能一次会滚动好几次,但是在具体的应用中这种太灵活的滚动在前面提到过的场景中必然会有误触发。直接将上面封装好的 throttle 函数拿过来稍微改下时间间隔同样能达到优化效果。

1 window.onmousewheel = throttle(function(){
2     // 滚轮滚动时的操作代码...
3 }, 200 );

鼠标滚轮设置 200 毫秒的延迟会有较理想的效果。

以上的一些优化方法大多是通过定时器来实现的,关键还是看如何灵活运用了。这些优化并不限于性能上的优化,还有交互效果上的优化,说到底就是以前端的角度出发,从细节入手来提升用户体验。

本文转自:http://stylechen.com/dom-event-optimize.html

浅谈DOM事件的优化的更多相关文章

  1. 前端性能优化--为什么DOM操作慢? 浅谈DOM的操作以及性能优化问题-重绘重排 为什么要减少DOM操作 为什么要减少操作DOM

    前端性能优化--为什么DOM操作慢?   作为一个前端,不能不考虑性能问题.对于大多数前端来说,性能优化的方法可能包括以下这些: 减少HTTP请求(合并css.js,雪碧图/base64图片) 压缩( ...

  2. 转:浅谈CSS在前端优化中一些值得注意的关键点

    前端优化工作中要考虑的元素多种多样,而合理地使用CSS脚本可以在很大程度上优化页面的加载性能,以下我们就来浅谈CSS在前端优化中一些值得注意的关键点: 当谈到Web的“高性能”时,很多人想到的是页面加 ...

  3. 浅谈DOM性能考虑

    浅谈DOM性能考虑 很多人都会忽视脚本对Web应用整体性能的影响.为保证应用的流畅运行,在为文档编写和应用脚本时,需要注意一些问题.一.尽量减少访问DOM和尽量减少标记    访问DOM的方式对脚本性 ...

  4. Js之浅谈dom操作

    JavaScript之浅谈dom操作 1.理解dom: DOM(Document Object Model ,文档对象模型)一种独立于语言,用于操作xml,html文档的应用编程接口. 怎么说,我从两 ...

  5. 浅谈tomcat中间件的优化【转】

    今天来总结一下tomcat的一些优化的方案,由于本人才疏学浅,写的不好,勿喷! tomcat对于大多数从事开发工作的童鞋应该不会很陌生,通常做为默认的开发环境来为大家服务,不过tomcat默认的一些配 ...

  6. [原创]浅谈H5页面性能优化方法

    [原创]浅谈H5页面性能优化方法 前阶段公司H5页面性能测试,其中测试时也发现了一些性能瓶颈问题,接下来我们在来谈谈H5页面性能优化,仅仅是一些常用H5页面性能优化措施,其实和Web页面性能优化思路大 ...

  7. MYSQL优化浅谈,工具及优化点介绍,mysqldumpslow,pt-query-digest,explain等

    MYSQL优化浅谈 msyql是开发常用的关系型数据库,快速.稳定.开源等优点就不说了. 个人认为,项目上线,标志着一个项目真正的开始.从运维,到反馈,到再分析,再版本迭代,再优化… 这是一个漫长且考 ...

  8. 浅谈Unity的渲染优化(1): 性能分析和瓶颈判断(上篇)

    http://www.taidous.com/article-667-1.html 前言 首先,这个系列文章做个大致的介绍,题目"浅谈Unity",因为公司和国内大部分3D手游开发 ...

  9. 浅谈Javascript事件模拟

    事件是用来描述网页中某一特定有趣时刻的,众所周知事件通常是在由用户和浏览器进行交互时触发,其实不然,通过Javascript可以在任何时间触发特定的事件,并且这些事件与浏览器创建的事件是相同的.这就意 ...

随机推荐

  1. 如何解决java高并发详细讲解

    对于我们开发的网站,如果网站的访问量非常大的话,那么我们就需要考虑相关的并发访问问题了.而并发问题是绝大部分的程序员头疼的问题, 但话又说回来了,既然逃避不掉,那我们就坦然面对吧~今天就让我们一起来研 ...

  2. Ambiguous mapping. Cannot map 'xxxController' method

    @GetMapping public JsonResp<List<DtoLandRegion>> getLandRegionList() { List<DtoLandRe ...

  3. 2020-07-04:tcp三次握手干了啥?time_wait什么时候出现?

    福哥答案2020-07-04:三次握手如下:1.SYN j2.ACK j+1,SYN k3.ACK k+1 time_wait出现在断开连接第四次挥手的时候出现.TIME_WAIT状态存在有两个原因. ...

  4. JavaScript 循环数组的时候调用方法中包含Promise的时候如何做到串行

    forEach是不能阻塞的, 默认[并行]方式 const list = [1, 2, 3] const square = num => { return new Promise((resolv ...

  5. Vue Vue.use() / Vue.component / router-view

    Vue.use Vue.use 的作用是安装插件 Vue.use 接收一个参数 如果这个参数是函数的话,Vue.use 直接调用这个函数注册组件 如果这个参数是对象的话,Vue.use 将调用 ins ...

  6. ASP.NET Core 奇技淫巧之接口代理转发

    前言 先讲讲本文的开发背景吧.. 在如今前后端分离的大背景下,咱的客户又有要求啦~ 要前后端分离~ 然因为种种原因..没办法用用纯前端的框架(其实是学习成本高,又没钱请前端开发人员)... 所以最终决 ...

  7. python设计模式之建造者模式

    python设计模式之建造者模式 ​ 建造者模式的适用范围:想要创建一个由多个部分组成的对象,而且它的构成需要一步接一步的完成.只有当各个部分都完成了,这个对象才完整.建造者模式表现为复杂对象的创建与 ...

  8. kafka-clients 1.0 内部响应接口文档

    AddOffsetsToTxnResponse version:0 name type defaultValue docString throttle_time_ms INT32 0 Duration ...

  9. 关于word2vec我有话要说

    写在前面的话: 总结一下使用word2vec一年来的一些经验,因为自己在做的时候,很难在网上搜到word2vec的经验介绍,所以归纳出来,希望对读者有用. 这里不介绍word2vec的原理,因为原理介 ...

  10. mycli工具mysql命令自动补全

    简介 MyCli 是一个 MySQL 的命令行客户端,可以实现自动补全和语法高亮.MyCli 也可用于 MariaDB 和Percona. 项目地址:http://mycli.net/ 安装 pip安 ...