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 相关文章推荐
IE与FireFox中的childNodes区别
Oct 20 Javascript
12款经典的白富美型—jquery图片轮播插件—前端开发必备
Jan 08 Javascript
JQuery操作iframe父页面与子页面的元素与方法(实例讲解)
Nov 20 Javascript
js调用iframe实现打印页面内容的方法
Mar 04 Javascript
js实现登陆遮罩效果的方法
Jul 28 Javascript
jQuery.Validate表单验证插件的使用示例详解
Jan 04 Javascript
Vue.js实现在下拉列表区域外点击即可关闭下拉列表的功能(自定义下拉列表)
May 30 Javascript
基于Bootstrap框架菜鸟入门教程(推荐)
Sep 17 Javascript
详解JS数值Number类型
Feb 07 Javascript
关于vue中watch检测到不到对象属性的变化的解决方法
Feb 08 Javascript
Vue2.0 给Tab标签页和页面切换过渡添加样式的方法
Mar 13 Javascript
vue将data恢复到初始状态 &amp;&amp; 重新渲染组件实例
Sep 04 Javascript
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
CentOS 上搭建 PHP7 开发测试环境
2017/02/26 PHP
PHP闭包定义与使用简单示例
2018/04/13 PHP
jQuery点击tr实现checkbox选中的方法
2013/03/19 Javascript
asp知识整理笔记3(问答模式)
2015/09/27 Javascript
JavaScript性能优化之小知识总结
2015/11/20 Javascript
jQuery头像裁剪工具jcrop用法实例(附演示与demo源码下载)
2016/01/22 Javascript
JavaScript基础重点(必看)
2016/07/09 Javascript
又一枚精彩的弹幕效果jQuery实现
2016/07/25 Javascript
Javascript中判断一个值是否为undefined的方法详解
2016/09/28 Javascript
Vue实例简单方法介绍
2017/01/20 Javascript
protractor的安装与基本使用教程
2017/07/07 Javascript
详解react-native-fs插件的使用以及遇到的坑
2017/09/12 Javascript
JS设计模式之状态模式概念与用法分析
2018/02/05 Javascript
vue+express+jwt持久化登录的方法
2019/06/14 Javascript
el-select 下拉框多选实现全选的实现
2019/08/02 Javascript
[01:04:22]2018DOTA2亚洲邀请赛 3.31 小组赛 B组 IG vs EG
2018/04/01 DOTA
浅谈Python实现2种文件复制的方法
2018/01/19 Python
Python+selenium 获取浏览器窗口坐标、句柄的方法
2018/10/14 Python
浅谈Python在pycharm中的调试(debug)
2018/11/29 Python
安装好Pycharm后如何配置Python解释器简易教程
2019/06/28 Python
python实现电子书翻页小程序
2019/07/23 Python
python 实现提取log文件中的关键句子,并进行统计分析
2019/12/24 Python
TENSORFLOW变量作用域(VARIABLE SCOPE)
2020/01/10 Python
python实现图像全景拼接
2020/03/27 Python
Django使用list对单个或者多个字段求values值实例
2020/03/31 Python
使用Python爬虫爬取小红书完完整整的全过程
2021/01/19 Python
python 实现IP子网计算
2021/02/18 Python
Champion澳大利亚官网:美国冠军运动服装
2018/05/07 全球购物
美国亚洲时尚和美容产品的一站式网上商店:Stylevana
2019/09/05 全球购物
司机检讨书
2014/02/13 职场文书
建筑工地宣传标语
2014/06/18 职场文书
2014年教研员工作总结
2014/12/23 职场文书
单位实习介绍信
2015/05/05 职场文书
建筑工程催款函
2015/06/24 职场文书
python入门之算法学习
2021/04/22 Python
Nginx 反向代理解决跨域问题多种情况分析
2022/01/18 Servers