在 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可以在任何时间触发特定的事件,并且这些事件与浏览器创建的事件是相同的.这就意 ...
随机推荐
- [转]解决The requested resource is not available的方法
此博文为转载博文,首先感谢原作者 HTTP Status 404(The requested resource is not available)异常主要是路径错误或拼写错误造成的,请按以下步骤逐一排 ...
- C#开发笔记之05-迭代器中的状态机(State Machine)到底是什么?
C#开发笔记概述 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/961 访问. 状态机可以理解为实现了备忘录模式(仅作为 ...
- STM32中 BOOT0 BOOT1设置(问题:程序下载进去但无法运行)
默认BOOT0接10K接地,BOOT1接10K接地 实际如果BOOT0不接10K到地,会导致程序能下载进去,但是无法运行情况
- SpringBoot---关于 WebMvcConfigurerAdapter 过时问题及解决方法
SpringBoot---关于 WebMvcConfigurerAdapter 过时问题及解决方法 环境: IDEA :2020.1 Maven:3.5.6 SpringBoot: 2.3.2 在Sp ...
- 编译Uboot时出错:【已解决】 /bin/bash: arm-linux-gcc: command not found dirname: missing operand Try 'dirname --help' for more information.
编译Uboot时出错: 错误信息如下: /bin/bash: arm-linux-gcc: command not found dirname: missing operand Try 'dirnam ...
- java Semaphore实现ABC三个线程循环打印
Semaphore位于java.util.concurrent包下.其中有两个重要的方法acquire()和release().acquire用来获取一个信号量,并且是阻塞型的,如果当前还有可用的信号 ...
- SpringBoot--- Shiro(拦截,认证)、Thymeleaf(模板引擎)
SpringBoot--- Shiro(拦截,认证).Thymeleaf(模板引擎) 环境 IDEA :2020.1 SpringBoot: 2.3.3 Java : 8 版本依赖: shiro- ...
- 构造vlan报文
#!/usr/bin/python from scapy.all import * packet = Ether(src='dc:99:14:01:a3:5e', dst='ff:ff:ff:ff:f ...
- gorm demo
package main import ( "fmt" "github.com/jinzhu/gorm" _ "github.com/jinzhu/g ...
- v-html渲染富文本图片宽高问题
v-html渲染富文本v-html是用来渲染html的节点及字符串的,但是渲染后富文本里的图片宽高会溢出所在div的区域但是使用css直接给img是没有办法设置img的宽高的,需要使用深层级来给img ...