1.事件流
1.1事件冒泡
IE的事件流叫做事件冒泡,事件开始时由最具体的元素节点接收,逐步向上传播。
<!DOCTYPE html>
<html>
<head>
<title>Event Bubbling Example</title>
</head>
<body>
<div id="myDiv">Click Me</div>
</body>
</html>
如果你在div设置了一个点击事件,则传播顺序:1.div 2.body 3.html 4.document
1.2 事件捕获
不太具体的节点应该更早的接收事件。在事件达到预期目标之前捕获它。
仍然是上面的例子,事件捕获顺序:1.document 2.html 3.body 4.div
1.3 DOM事件流
DOM事件流分为三个阶段:事件捕获、目标阶段、事件冒泡。
2.事件处理程序
事件是用户或者浏览器自身执行的动作。响应某个事件的函数叫做事件处理程序。
2.1 HTML事件处理程序
通过html的方式实现一个onclick事件
<input type = "button" onclick = "alert("hellp")">
2.2 DOM0级事件处理程序
这也是现在最常用的一种方法。为啥常用?原因一是简单,原因二具有跨浏览器优势。
var btn = document.getElementById("myBtn");
btn.onclick = function () {
alert("hello");
};
2.3 DOM2级事件处理程序
“DOM2级事件”定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListener()和removeEventListener()。
所有的DOM节点都包含这两个方法。接收三个参数:要处理的时间名、作为事件处理程序的函数和布尔值。最后这个布尔值是true,表示在捕获节点调用时间处理程序;如果是false,表示在冒泡阶段调用时间处理程序。
var btn = document.getElementById("myBtn");
btn.addEventListener("click", function(){
alert(this.id);
}, false);
btn.addEventListener("click", function(){
alert("Hello world!");
}, false);
2.4 IE事件处理程序
IE实现了DOM中类似的两个方法:attachEvent()和detachEvent()。这两个方法接收相同的两个参数:事件处理程序名称与时间处理程序函数。IE8及更早的版本只支持事件冒泡,所以通过attachEvent()添加的时间处理程序都会被添加到冒泡阶段。
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(){
alert("Clicked");
});
btn.attachEvent("onclick", function(){
alert("Hello world!");
});
2.5 跨浏览器的事件处理程序
要保证处理事件的带啊能在大多数浏览器下一致的执行,只需要关注冒泡阶段。
第一个要创建的放大是addHandler(),它的作用是视情况而定分别使用DOM0级方法、DOM2级方法或IE方法来添加事件。addHandle()接受三个参数:要操作的元素、事件名称和事件处理程序函数。
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;
}
},
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;
} }
};
3.事件对象
在触发DOM上的某个事件时,会产生一个event对象,这个对象中包含素有时间有关的信息。事件的元素、事件的类型及其他相关信息。例如,鼠标点击导致的事件,可以获取到鼠标点击的位置;键盘操作导致的事件,会包含与按下的键有关的信息。
3.1 DOM中的时间对象
兼容DOM的浏览器会将一个event对象传入到时间处理程序中。无论指定时间处理程序时使用什么方法,都会传入event对象。
var btn = document.getElementById("myBtn");
btn.onclick = function(event){
alert(event.type); //"click"
};
btn.addEventListener("click", function(event){
alert(event.type); //"click"
}, false);
关于Event对象包含的属性与方法
属性/方法 | 类型 | 读/写 | 说明 |
---|---|---|---|
bubbles | boolean | 只读 | 表明时间是否冒泡 |
cancelable | boolean | 只读 | 表名是否可以取消事件默认行为 |
currentTarget | Element | 只读 | 其事件处理程序当前正在处理事件的那个元素 |
defaultPrevented | boolean | 只读 | 为true表示已经调用了preventDefault() |
detail | Integer | 只读 | 与事件相关的细节信息 |
eventPhase | Integer | 只读 | 调用时间处理程序的阶段,1表示捕获阶段,2表示处于目标,3表示冒泡阶段 |
preventDefault() | Function | 只读 | 取消事件默认行为 |
stopImmediatePropagation() | Function | 只读 | 取消事件的进一步捕获或冒泡,同时阻止任何事件处理程序被调用 |
stopPropagation() | Function | 只读 | 取消事件的进一步捕获或冒泡,如果bubbles为true,则可以使用这个方法 |
target | Element | 只读 | 事件的目标 |
trusted | boolean | 只读 | 为true表示事件是浏览器生成。false表示事件使用开发人员通过JS创建 |
type | String | 只读 | 被触发事件的类型 |
view | AbstractView | 只读 | 与事件关联的抽象视图。等同于发生事件的window对象 |
在对象处理程序内部,对象this扥估currentTarget的值。
var btn = document.getElementById("myBtn");
btn.onclick = function(event) {
alert(event.currentTarget === this); //true
alert(event.target === this); //true
};
4.事件类型
事件类型分类:UI事件、焦点事件、鼠标事件、滚轮事件、文本事件、键盘事件、合成事件、变动事件。
4.1 UI事件
1.load事件:JS中最常用的就是load事件。当页面加载后就会触发window上的load事件。如何定义onload事件呢?可以看下demo
第一种,JS声明
EventUtil.addHandler(window, "load", function(event){
alert("Loaded");
});
第二种,标签属性
<body onload="alert('Loaded!')">
2.unload事件:文档被完全卸载后触发。只要用户从一个页面切换到另一个页面就会触发unload。利用这个事件最多的情况是清除引用,避免内存泄露。
第一种,JS声明
EventUtil.addHandler(window, "unload", function(event){
alert("Unloaded");
});
第二种,标签属性
<body onunload="alert('Loaded!')">
3.resize事件:当浏览器窗口被调整到一个新的高度或宽度时,就会触发resize事件。注意resize事件会频繁被触发,所以在尽量不要书写大量运算逻辑,会导致浏览器变慢。
第一种,JS声明
EventUtil.addHandler(window, "resize", function(event){
alert("Resized");
});
第二种,标签属性
<body onresize="alert('Loaded!')">
4.scroll事件:当用户滚动带滚动条的元素内容时触发。在window对象上发生的,表示页面中响应元素的变化。跟resize事件类似,scroll会频发触发。所以在尽量不要书写大量运算逻辑,会导致浏览器变慢
EventUtil.addHandler(window, "scroll", function(event){
if (document.compatMode == "CSS1Compat"){
alert(document.documentElement.scrollTop);
} else {
alert(document.body.scrollTop);
}
});
4.2 焦点事件(这里就不写demo了,会对事件做一个详细的分析)
- blur:在元素市区焦点时触发。这个事件不会冒泡(但是可以捕获阶段监听到)
- focus:在元素获得焦点时触发。这个事件不会冒泡(但是可以捕获阶段监听到)
- focusion:在元素获得焦点时触发。这个事件会冒泡
- focusout:在元素失去焦点时触发。这个事件会冒泡
4.3 滚动与滚轮事件
- click:在用户单击主鼠标按钮或者回车键触发
- dblclick:在用户双击主鼠标按钮时触发
- mousedown:在用户按下任意鼠标按钮时触发。
- mouseenter:鼠标光标从元素外部首次移动到元素范围内触发。(IE、Firefox 9+和Opera支持)
- mouseleave:在位于元素上方的鼠标光标移动到元素范围之外时候触发。(IE、Firefox 9+和Opera支持)
- mousemove:当鼠标指针在元素内部移动时重复触发。
- mouseout:在鼠标指针位于一个元素上方,然后用户将其移入另一个元素时触发。
- mouseover:在鼠标指针位于一个元素外部,然后用户将其移入另一个元素边界之内时触发。
- mouseup:在用户释放鼠标按钮时触发。
1.客户区坐标位置(整个浏览器去掉工具栏等其他辅助工具的位置)
var div = document.getElementById("MyDiv");
EventUtil.addHandler(div, "click", function(event){
event = EventUtil.getEvent(event);
alert("Client coordinates: " + event.clientX + "," + event.clientY);
});
2.页面坐标位置
var div = document.getElementById("MyDiv");
EventUtil.addHandler(div, "click", function(event){
event = EventUtil.getEvent(event);
alert("Page coordinates: " + event.pageX + "," + event.pageY);
});
3.屏幕坐标位置(获取的是整个用户操作系统界面的坐标)
var div = document.getElementById("myDiv");
EventUtil.addHandler(div, "click", function(event){
event = EventUtil.getEvent(event);
alert("Screen coordinates: " + event.screenX + "," + event.screenY);
});
4.修改键
修改键就是Shift、Ctrl、Alt,这些经常被用来修改鼠标性情。因此DOM规定了四个属性,来修改这些按键的状态:shiftKey、ctrlKey、altKey和metaKey。这些属性都是布尔值,如果这些按键按下了则为true,否则为false。
var div = document.getElementById("myDiv");
EventUtil.addHandler(div, "click", function(event){
event = EventUtil.getEvent(event);
var keys = new Array();
if (event.shiftKey){
keys.push("shift");
}
if (event.ctrlKey){
keys.push("ctrl");
}
if (event.altKey){
keys.push("alt");
}
if (event.metaKey){
keys.push("meta");
}
alert("Keys: " + keys.join(","));
});
4.4 键盘与文本事件
- keydown:当用户按下键盘上任意键时触发。按住不放,重复执行此事件
- keypress:当用户按下键盘上的字符键时触发。按住不放,重复执行此事件
- keyup:当用户释放按键时触发
1.键码
键盘上每个按键都有一个keyCode属性用于标识按键的。
var textbox = document.getElementById("myText");
EventUtil.addHandler(textbox, "keyup", function(event){
event = EventUtil.getEvent(event);
alert(event.keyCode);
});
2.字符编码
浏览器event对象都支持一个charCode属性,这个属性只有在发生keypress事件才有值,而且这个值是安县哪个键锁代表的字符的ASCII编码。通常用来检验浏览器字符集。
3.textInput事件
用户在可编辑区域中输入字符时,就会触发这个事件。
var textbox = document.getElementById("myText");
EventUtil.addHandler(textbox, "textInput", function(event){ event = EventUtil.getEvent(event);
alert(event.data);
});
5.内存与性能
5.1 事件委托
对事件处理程序过多的时候,就可以通过委托的方式去解决。事件委托利用了事件冒泡。指定一个事件处理程序,就可以管理一类型所有的事件。
<ul id="myLinks">
<li id="goSomewhere">Go somewhere</li>
<li id="doSomething">Do something</li>
<li id="sayHi">Say hi</li>
</ul>
function getEvent(){
var list = document.getElementById("myLinks");
EventUtil.addHandler(list, "click", function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
}
}
5.2 移除事件处理程序
每当事件处理程序指定元素时,运行中的浏览器代码与支持页面交互的JS代码会建立一个链接。这种链接越多,页面执行越慢。可以两种方式规避这个问题,可以采用事件委托技术限制建立连接数。另外,在不需要的时候移除事件处理程序。
btn.onclick = funciotn(){
//执行某些操作
btn.onclick = null; //移除事件处理程序
document.getElementById("myDiv").innerHTML = "Processing...";
};