事件
事件:用户与浏览器特定的交互瞬间。
内存和性能
事件处理程序为现代web浏览器提供了交互能力,但有时也不能一味地为页面添加事件处理程序,在JavaScript中,添加到页面中的事件处理程序的数量直接影响着页面整体的运行性能。添加到页面中的事件处理程序越多,那么所占用的内存也多,运行性能就会下降。而且事先指定事件处理程序面导致的DOM访问次数也会增多。对于如何利用好事件处理程序对页面运行性能的改善也是有帮助的。
事件委托
对于“事件处理程序过多”的解决方法就是
事件委托。
事件委托运用到了事件冒泡,只指定一个事件处理程序,来管理这一类的事件。
事件委托是运用了事件冒泡特性。例如:click事件会一直冒泡到document对象上。也就是说,我们可以为页面指定 一个onclick事件处理程序,而不必为每个可单击的元素一一指定事件处理程序。
<ul id="liList">
<li id="li1">sayGood</li>
<li id="li2">sayHi</li>
<li id="li3">sayId</li>
</ul>
例子中包含3个被单击后会执行操作的列表项,按照传统方法,我们会一一为它们指定事件处理程序。
var li1 = document.getElementById("li1");
li1.onclick = function (event) {
console.log("good");
};
var li2 = document.getElementById("li2");
li2.onclick = function (event) {
console.log("Hi");
};
var li3 = document.getElementById("li3");
li3.onclick = function (event) {
console.log(event.id);
};
如果是在一个复杂的web程序中,那么就会有很多的代码用于指定事件处理程序了,这样会占用更多的内存,导致运行性能下降。
此时我们可以运用事件委托,
只需在DOM层次中的尽量高的节点上指定一个事件处理程序即可。这个例子中,可以在ul这个节点上指定事处理程序。
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript</title>
</head>
<body>
<ul id="liList">
<li id="li1">sayGood</li>
<li id="li2">sayHi</li>
<li id="li3">sayId</li>
</ul>
<script>
/* 在此处书写javascript代码 */
var liList = document.getElementById("liList");
//只在ul上指定一个事件处理程序
liList.onclick = function (event) {
//由event.target得到事件目标
switch (event.target.id) {
case "li1":
console.log("good");
break;
case "li2":
console.log("Hi");
break;
case "li3":
console.log(this.id);
break;
}
};
</script>
</body>
</html>
效果:
当点击列表项时,就会触发click事件。由于每个列表项都是DOM上的节点,而且它们的事件会冒泡,最终会传播到ul节点上,最终会被这个函数处理。
有时我们也可以为document指定一个事件处理程序,用于处理页面上某一类型的事件。
事件委托与传统的指定事件处理程序比较其优点在于:
1、设置事件处理程序所需时间少,只添加一个需要的事件处理程序DOM引用更少。
2、添加的事件处理程序少,那么所占用的内存就好,提高了运行性能。
移除不再需要的事件处理程序
除了前面所述的事件委托方法来提高web运行性能和减少占用内存外,
移除事件处理程序也是解决这个问题的一个重要方法,移除不需要的、空的事件处理程序。
注:移除事件处理程序的方法:就是给事件处理程序赋值ull。
造成以上问题的有两个原因:
1、将带有事件处理程序的元素通过纯DOM操作来删除,如:removeChild()和replaceChild()。
2、就是通过InnerHTML替换页面中原有的内容,这样虽然元素被替换了,但事件处理程序仍然与元素保持引用的关系。
也就是说,虽然通过以上方法将元素删除了或替换了,但与其保持关系的事件处理程序仍然在内存中,这样事件处理程序在内存中越积越多,最后导致web运行变慢,性能下降。
通过innerHTML替换内容:
var liList = document.getElementById("liList");
liList.onclick = function (event) {
//其它操作
//直接通过innerHTML替换元素
liList.innerHTML = "字符串"; //麻烦了
};
这样虽然用字符串将ul元素替换了,但与ul元素保持关系的事件处理程序还在内存中。我们最好手工移除事件处理程序:
var liList = document.getElementById("liList");
liList.onclick = function (event) {
//通过给事件处理程序赋值null,来移除事件。
liList.onclick = null;
//再将元素替换掉。
liList.innerHTML = "字符串";
};
导致“空事件处理程序”的原因之一,就是卸载页面。如果在卸载页面之前没有清除掉事件处理程序,那么就会停留在内存中。当加载完页面或卸载页面(可能是页面之间来回切换),内存中就会增加事件事件处理程序,内存中对象的条目就会增多,因为没有清除事件处理程序,那么占用的内存就没有释放。
最好的方法,就是在页面卸载之前,通过onunload事件将所有事件处理程序清除干净。