让学习“上瘾”,成为更好的自己!!!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>内存和性能</title>
</head>
<body>
<ul id="myLinks">
<li id="goSomewhere">go somewhere</li>
<li id="doSomething">do something</li>
<li id="sayHi">say hi</li>
</ul>
<div id="myDiv">
<input id="myBtn" type="button" name="" id="" value="click me" >
</div>
<script>
/*
在JavaScript中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能
1,事件委托 --> “事件处理程序过多”
事件委托利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件
使用事件委托,只需在DOM树中尽量高的层次上添加一个事件处理程序!!
2,移除事件处理程序 --> “空事件处理程序”
*/
// 【掌握!!】
var EventUtil = {
addHandler:function(element, type, handler){
if(element.addEventListener){
element.addEventListener(type, handler, false);
} else if(element.attachEvent){
element.attachEvent('on'+type,handler);
}else{
element['on'+type] = handler;
}
},
getEvent:function(event){
return event ? event : window.event;
},
getTarget:function(event){
return event.target || event.srcElement;
},
preventDefault:function(event){
if(event.preventDefault){
event.preventDefault();
}else {
event.returnValue = false;
}
},
removeHandler:function(element, type, handler){
if(element.removeEventListener){
element.removeEventListener(type, handler, false);
} else if(element.detachEvent){
element.detachEvent('on'+type,handler);
}else{
element['on'+type] = null;
}
},
stopPropagation:function(event){
if(event.stopPropagation){
event.stopPropagation();
}else {
event.cancelBubble = true;
}
}
};
// 使用事件委托,只需在DOM树中尽量高的层次上添加一个事件处理程序!!
var list = document.getElementById('myLinks');
console.log(list);
EventUtil.addHandler(list, 'click', function(event){
event = EventUtil.getEvent(event);
console.log(event);
var target = EventUtil.getTarget(event); // target事件目标是被单击的列表项
switch(target.id){
case 'doSomething':
document.title = 'i changed the document\'s title';
break;
case 'goSomewhere':
location.href = 'http://wrox.com';
break;
case 'sayHi':
alert('hi');
break;
}
})
// 【总结】 所有用到按钮的事件(多数鼠标事件和键盘事件)都合适用这种“事件委托”的技术!
// 可以考虑为document对象添加一个事件处理程序,用以处理页面上发生的某种特定类型的事件
// 最适合采用事件委托技术的事件包括click, mousedown, mouseup, keydown, keyup and keypress
// 2,移除事件处理程序
// 每当将事件处理程序指定给元素时,运行中的浏览器代码与支持页面交互的JavaScript代码之前就会建立一个链接
// 连接越多,页面执行时间就越慢
// 造成“空事件处理程序”的2种情况
// 1, 从文档中移除带有事件处理程序的元素时
// 更多的是发生在使用innerHTML替换页面中的某一部分时。
// 如果带有事件处理程序的元素被innerHTML删除了,那么原来添加到元素中的事件处理程序极有可能“无法”被当做垃圾回收
// var btn = document.getElementById('myBtn');
// btn.onclick = function(){
// // do someting
// document.getElementById('myDiv').innerHTML = 'processing...'
// // 在<div>元素上设置innerHTML可以把按钮移走,但事件处理程序仍然与按钮保持引用关系
// }
// 好的做法如下:
// 如果知道某个元素即将被移除,那么最好手工移除对应的事件处理程序
var btn = document.getElementById('myBtn');
btn.onclick = function(){
// do someting
btn.onclick = null; // “移除事件处理程序”
document.getElementById('myDiv').innerHTML = 'processing...'
// 在<div>元素上设置innerHTML属性前,先移除按钮的事件处理程序,确保内存可以被再次利用,而从DOM中移除按钮也很干净了!
// 【注意】在事件处理程序中删除按钮也能阻止事件冒泡。目标元素在文档中是事件冒泡的前提
}
// 2, 卸载页面时
// 如果在页面被卸载之前没有清理干净事件处理程序,那他们就会滞留在内存中
// 每次加载完页面在卸载页面时(可能是在两个页面来回切换,也可以是单击了“刷新”按钮),内存中滞留的对象数目就会增加,
// 因为时间处理程序的占用内存并没有被释放
// 好的做法如下:
// 在页面卸载之前,先通过onunload事件处理程序移除所有事件处理程序
// 总结为:只要是通过onload事件处理程序添加的东西,最后都要通过onunload事件处理程序将他们移除(缓存不会被放在bfcache中!!)
</script>
</body>
</html>