在 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. ReentrantLock与synchronized 源码解析

    一.概念及执行原理   在 JDK 1.5 之前共享对象的协调机制只有 synchronized 和 volatile,在 JDK 1.5 中增加了新的机制 ReentrantLock,该机制的诞生并 ...

  2. Memcached高可用组件之repcached

    在前边的tomcat session server msm的那篇博客我们用memcached做tomcat session服务器,默认官方memcached是不支持主从同步的,为了解决memcache ...

  3. python处理转载博客html

    前景 在转载别人博客的时候通常我们会通过复制html然后放到编辑器里面, 但是通常html里有很多杂七杂八的东西, 比如script, svg这些标签导致排版出现问题 例如由lu标签引起的 由svg标 ...

  4. Android 开发学习进程0.12 自定义view activity的属性

    设置类似钉钉或tel的圆形用户名首字母头像 设置有两种方法,一是使用已有的库或自定义的view组件,但如果确定只是文字头像,也可使用textview的backgrou属性,调整资源文件使textvie ...

  5. 基于OpenSIPS 实现分机注册服务服务器

    呼叫中心平台中坐席是不可或缺的一环,而坐席打电话自然需要使用办公分机.通常情况下我们通过软交换平台FreeSWITCH.Asterisk即可搭建分机注册服务. 但单台FreeSWITCH或Asteri ...

  6. chained get value from nested json

    static getValueByKey(o, p, defaultValue = false) { return p.split('.').reduce((r, k) => { if (typ ...

  7. python读取数据文件:pandas包详解

    本文转载自https://blog.csdn.net/brucewong0516/article/details/79092579 pandas包是一个高效的文件读取工具,适用于txt,excel,等 ...

  8. 计算机网络-链路层(2)多路访问控制协议(multiple access control protocol)

    单一共享广播信道,如果两个或者两个以上结点同时传输,会互相干扰(interference) 冲突(collision):结点同时接收到两个或者多个信号→接收失败! MAC协议采用分布式算法决定结点如何 ...

  9. pytest与Allure集成

    1.窗口的方式 重启jenkins,重新连接,继续上次的内容.(注意:点击launch,重新下载slave-agent文件,然后双击slave-agent文件进行连接.上次下载的slave-agent ...

  10. .Net MongoDB批量修改集合中子集合的字段

    环境:.Net Core 3.1 (需要导入.Net MongoDB的驱动) 模型 /// <summary> /// 收藏 /// </summary> public cla ...