JavaScript 事件对内存和性能的影响


Posted in Javascript onJanuary 22, 2017

虽说事件处理程序可以为现代 Web 页面添加很强的交互能力,但是不分青红皂白就添加大量的事件处理程序绝对是一种愚蠢的行为。

我们来分析一下:事件处理程序本质上是一种函数,是一种对象,存放在内存中,设置大量的事件处理程序会使内存中的对象变多,Web 程序的性能会变得越来越差,用户体验很不好。

为了更好地利用好事件处理程序,便出现了事件委托,用来提升性能。

事件委托

事件委托(event delegation):把若干个子节点上的相同事件的处理函数绑定到它的父节点上去,在父节点上统一处理从子节点冒泡上来的事件,这种技术就叫做事件委托。

补充一下:事件委托并不局限于父节点与子节点之间。也可以这样玩,比如页面文档中有好多个处在不同位置地 button,都是绑定 click 事件,使用事件委托,我们可以把这些个事件统一绑定到 body 元素,然后再进行处理(虽然一般很少这么用)。

下面举例子逐步说明事件委托的优势:

<ul id="parent-list">
 <li id="list-1">List 1</li>
 <li id="list-2">List 2</li>
 <li id="list-3">List 3</li>
 <li id="list-4">List 4</li>
 <li id="list-5">List 5</li>
</ul>

假设有上面的代码,我们现在有一个需求:就是无论单击上面的列表(ul)的哪个子列表(li),都会弹出一个框,来显示我们点击了哪个子列表。

需求不难吧?有了需求,接下来是该写 js 代码了,现在有两种方法放在你眼前:1. 为每个 li 子元素绑定 click 事件,然后设置处理函数; 2. 利用事件委托,为 ul 父元素绑定 click 事件,然后设置处理函数

// 方法一
var list1 = document.getElementById("list-1");
list1.addEventListener("click",function(){
 alert(this.firstChild.nodeValue);
},false);
var list2 = document.getElementById("list-2");
list2.addEventListener("click", function() {
 alert(this.firstChild.nodeValue);
}, false);
var list3 = document.getElementById("list-3");
list3.addEventListener("click", function() {
 alert(this.firstChild.nodeValue);
}, false);
var list4 = document.getElementById("list-4");
list4.addEventListener("click", function() {
 alert(this.firstChild.nodeValue);
}, false);
var list5 = document.getElementById("list-5");
list5.addEventListener("click", function() {
 alert(this.firstChild.nodeValue);
}, false);
// 方法二
var parentList = document.getElementById("parent-list");
parentList.addEventListener("click",function(){
 var target = event.target;
 if(target.nodeName.toLowerCase() === "li"){
 alert(target.firstChild.nodeValue);
 }
},false);

看着上面的代码,我这里写几点方法二的优点:1. 减少了访问 DOM 的次数,提升了性能;2. 将子元素的事件处理程序统一绑定到其父元素,减少了对内存的占用;3. 可以更好地管理事件处理程序,比如移除对某个事件处理程序的引用

注意:如果对各个子元素的需求不一样,我们还可以这样来改写上面的方法二:

// 方法二
var parentList = document.getElementById("parent-list");
parentList.addEventListener("click",function(){
 var target = event.target;
 if(target.nodeName.toLowerCase() === "li"){
 switch(target.id){
  case "list-1":
  alert("学的越多,越觉得自己无知!");
  break;
  case "list-2":
  alert("爱是一种艺术!");
  break;
  case "list-3":
  target.innerHTML = "呵呵,我改了啊!";
  break;
  case "list-4":
  target.style.background = "#aaa";
  break;
  case "list-5":
  target.style.color = "red";
  target.style.fontSize = "2em";
  break;
  default:
  break;
 }
 }
},false);

因为事件委托依赖事件冒泡机制,所以,并不是所有的事件都可以进行事件委托。

最适合采用事件委托的事件包括:click、mousedown、mouseup、keydown、keyup 和 keypress。

事件委托只是一种非常不错的事件绑定的思想,所以不应该拘泥于上面的例子,要活学活用! ^_^

移除事件处理程序

我们前面说过,事件处理程序存在于内存中,每当将事件处理程序指定给元素时,运行中的浏览器代码与支持页面交互的 JavaScript 代码之间就会建立一个连接。这种连接越多,页面执行就越慢。前面所说的事件委托就是用来限制建立的连接数量。

还有,就是内存中那些使用完后不再使用的事件处理程序,如果不释放掉,也会影响 Web 应用程序的内存和性能。

<button id="button">提交</button>
var button = document.getElementById("button");
button.onclick = function(){
 // 提交某个表单的操作代码
 button.onclick = null; // 移除事件处理程序
 event.target.firstChild.nodeValue = "提交中。。。";
};

总的原则就是:移除掉那些过时不再使用的事件处理程序,释放内存!

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
Array对象方法参考
Oct 03 Javascript
获取当前点击按钮的id用this.id实现
Mar 17 Javascript
jQuery晃动层特效实现方法
Mar 09 Javascript
使用jQuery获取data-的自定义属性
Nov 10 Javascript
JS实现图片局部放大或缩小的方法
Aug 20 Javascript
jQuery中extend函数简单用法示例
Oct 11 jQuery
vue之将echart封装为组件
Jun 02 Javascript
你可能从未使用过的11+个JavaScript特性(小结)
Jan 08 Javascript
解决vue.js中settimeout遇到的问题(时间参数短效果不稳定)
Jul 21 Javascript
在Uni中使用Vue的EventBus总线机制操作
Jul 31 Javascript
vue-video-player实现实时视频播放方式(监控设备-rtmp流)
Aug 10 Javascript
如何在vue中使用video.js播放m3u8格式的视频
Feb 01 Vue.js
Angular指令封装jQuery日期时间插件datetimepicker实现双向绑定示例
Jan 22 #Javascript
Bootstrap 下拉多选框插件Bootstrap Multiselect
Jan 22 #Javascript
JavaScript 详解预编译原理
Jan 22 #Javascript
JavaScript中匿名函数的递归调用
Jan 22 #Javascript
Javascript中字符串和数字的操作方法整理
Jan 22 #Javascript
loading动画特效小结
Jan 22 #Javascript
全面总结Javascript对数组对象的各种操作
Jan 22 #Javascript
You might like
乐信RP2100的电路分析和打磨
2021/03/02 无线电
PHP分页显示的方法分析【附PHP通用分页类】
2018/05/10 PHP
Yii框架视图、视图布局、视图数据块操作示例
2019/10/14 PHP
javascript 支持ie和firefox杰奇翻页函数
2008/07/22 Javascript
JavaScript中两个感叹号的作用说明
2011/12/28 Javascript
javascript模拟枚举的简单实例
2014/03/06 Javascript
JS通过分析userAgent属性来判断浏览器的类型及版本
2014/03/28 Javascript
js创建表单元素并使用submit进行提交
2014/08/14 Javascript
jQuery+css3实现文字跟随鼠标的上下抖动
2015/07/31 Javascript
js实现二级菜单渐隐显示
2015/11/03 Javascript
写给小白的JavaScript引擎指南
2015/12/04 Javascript
通过设置CSS中的position属性来固定层的位置
2015/12/14 Javascript
关于Javascript中defer和async的区别总结
2016/09/20 Javascript
NodeJs读取JSON文件格式化时的注意事项
2016/09/25 NodeJs
基于Vue2的移动端开发环境搭建详解
2016/11/03 Javascript
vue引入js数字小键盘的实现代码
2018/05/14 Javascript
vue-cli 使用vue-bus来全局控制的实例讲解
2018/09/15 Javascript
基于vue实现滚动条滚动到指定位置对应位置数字进行tween特效
2019/04/18 Javascript
vue+导航锚点联动-滚动监听和点击平滑滚动跳转实例
2019/11/13 Javascript
JavaScript中window和document用法详解
2020/07/28 Javascript
[43:32]2014 DOTA2华西杯精英邀请赛 5 25 LGD VS NewBee第一场
2014/05/26 DOTA
[42:22]DOTA2上海特级锦标赛C组小组赛#1 OG VS Archon第一局
2016/02/27 DOTA
django 2.2和mysql使用的常见问题
2019/07/18 Python
python中读入二维csv格式的表格方法详解(以元组/列表形式表示)
2020/04/24 Python
keras模型保存为tensorflow的二进制模型方式
2020/05/25 Python
使用keras框架cnn+ctc_loss识别不定长字符图片操作
2020/06/29 Python
python如何删除列为空的行
2020/07/17 Python
澳大利亚当地最大的时装生产商:Cue
2018/08/06 全球购物
会计专业自荐信范文
2013/12/02 职场文书
酒店营销策划方案
2014/02/07 职场文书
党员创先争优心得体会
2014/09/11 职场文书
大学生职业生涯十年规划书范文
2014/09/17 职场文书
2015年中个人总结范文
2015/03/10 职场文书
机关干部正风肃纪心得体会
2016/01/15 职场文书
导游词之麻姑仙境
2019/11/18 职场文书
python实现自定义日志的具体方法
2021/05/28 Python