参考文章一
事件就是文档或浏览器窗口中发生的一些特定的交互瞬间,是可以被 JavaScript 侦测到的行为
)在捕获阶段不会接收事件。也就是在捕获阶段,事件从document到
再到
就停止了。
- 处于目标阶段 :事件在
上发生并处理。但是事件处理会被看成是冒泡阶段的一部分。
- 事件冒泡阶段 :事件又传播回文档。
三、两种事件流模型
(一)事件冒泡(IE的事件流)
事件冒泡即事件开始时,由最具体的元素接收(也就是事件发生所在的节点),然后逐级传播到较为
不具体的节点。
(二)事件捕获(Net Communicator的事件流)
事件捕获的思想是不太具体的节点应该更早的接收到事件,而具体的节点应该最后接收到事件
由于老版本浏览器不支持,很少有人使用事件捕获。建议使用事件冒泡。
四、事件绑定——事件处理程序
(一)在DOM中直接绑定事件
我们可以在DOM元素上绑定onclick、onmouseover、onmouseout、onmousedown、onmouseup
、ondblclick、onkeydown、onkeypress、onkeyup等。
<input type="button" value="click me" onclick="hello()">
<script>
function hello(){
alert("hello world!");
}
script>
(二)在JavaScript代码中绑定事件
将一个函数赋值给一个事件处理程序属性,在元素的作用域中运行,程序中的this引用当前元素
var btn = document.getElementById("myBtn");
btn.onclick = function(){
alert(this.id); //"myBtn"
}
(三)使用事件监听绑定事件
绑定事件的另一种方法是用 addEventListener() 或 attachEvent() 来绑定事件监听函数。
五、事件监听
(一)“DOM2级事件”定义了两个方法,处理和删除addEventListener()和removeEventListener()
document.addEventListener(event, function, useCapture);
document.removeEventListener(event, function, useCapture)
document.addEventListener("click", myFunction);
function myFunction() {
document.getElementById("demo").innerHTML = "Hello World";
}
可以给元素添加多个事件,会按照添加顺序触发
document.addEventListener("click", myFunction);
document.addEventListener("click", someOtherFunction);
// 在文档中添加事件句柄
document.addEventListener("mousemove", myFunction);
// 移除文档中的事件句柄
document.removeEventListener("mousemove", myFunction);
(二)IE事件处理程序的两个方法——attachEvent()和detachEvent()
事件处理程序会在全局作用域运行,此时的this等于window,和“DOM2级事件”的不同点
element.attachEvent(event, function)
element.detachEvent(event, function)
- event:(必需)事件类型。需加“on“,例如:onclick。
- function:(必需)指定要事件触发时执行的函数。
<input type="button" value="click me" id="btn2">
<script>
document.getElementById("btn2").attachEvent("onclick",hello);
function hello(){
alert("hello world!");
}
script>
(三)事件监听的优点
- 可以绑定多个事件。
- 可以解除相应的绑定
六、事件委托
事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
使用事件委托,只需在DOM树中尽量最高的层次上添加一个事件处理程序
传统写法:
<ul id="list">
<li id="item1" >item1li>
<li id="item2" >item2li>
<li id="item3" >item3li>
ul>
<script>
var item1 = document.getElementById("item1");
var item2 = document.getElementById("item2");
var item3 = document.getElementById("item3");
item1.onclick = function(){
alert("hello item1");
}
item2.onclick = function(){
alert("hello item2");
}
item3.onclick = function(){
alert("hello item3");
}
script>
事件委托的写法:
<ul id="list">
<li id="item1" >item1li>
<li id="item2" >item2li>
<li id="item3" >item3li>
ul>
<script>
var item1 = document.getElementById("item1");
var item2 = document.getElementById("item2");
var item3 = document.getElementById("item3");
document.addEventListener("click",function(event){
var target = event.target;
if(target == item1){
alert("hello item1");
}else if(target == item2){
alert("hello item2");
}else if(target == item3){
alert("hello item3");
}
})
script>
事件委托的优点
- 整个页面占用的内存更少,提高整体性能
- 设置的事件处理程序所需时间更少,所需的DOM引用更少
七、事件对象(event)
参考这里
重点参考文章
在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含所有与事件相关的信息
(一)DOM中的事件对象
event.type属性表示事件类型,例如"click"
event的属性和方法如下:
(二)IE中的事件对象
在使用DOM0级方法添加事件处理程序时,event对象作为window对象的一个属性
btn.onclick = function(){
var event = window.event;
alert("event.type"); //"click"
}
event的属性和方法如下:
八、阻止冒泡
(一)stopPropagation() 方法
该方法立即停止事件在DOM层次上的传播,即取消进一步的事件捕获或冒泡
(二)cancelBubble属性—–只能取消冒泡
window.event.cancelBubble = true;
九、取消事件的默认行为
(一)preventDefault()方法
只有cancelBubble属性设置为true的事件,才可以使用这个方法
event.preventDefault();
(二)returnValue属性
window.event.returnValue=false;
(三)js的return false
十、写一个通用的事件侦听器函数
markyun.Event = {
// 页面加载完成后
readyEvent : function(fn) {
if (fn==null) {
fn=document;
}
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = fn;
} else {
window.onload = function() {
oldonload();
fn();
};
}
},
// 视能力分别使用dom0||dom2||IE方式 来绑定事件
// 参数: 操作的元素,事件名称 ,事件处理程序
addEvent : function(element, type, handler) {
if (element.addEventListener) {
//事件类型、需要执行的函数、是否捕捉
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent('on' + type, function() {
handler.call(element);
});
} else {
element['on' + type] = handler;
}
},
// 移除事件
removeEvent : function(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.datachEvent) {
element.detachEvent('on' + type, handler);
} else {
element['on' + type] = null;
}
},
// 阻止事件 (主要是事件冒泡,因为IE不支持事件捕获)
stopPropagation : function(ev) {
if (ev.stopPropagation) {
ev.stopPropagation();
} else {
ev.cancelBubble = true;
}
},
// 取消事件的默认行为
preventDefault : function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
// 获取事件目标
getTarget : function(event) {
return event.target || event.srcElement;
},
// 获取event对象的引用,取到事件的所有信息,确保随时能使用event;
getEvent : function(e) {
var ev = e || window.event;
if (!ev) {
var c = this.getEvent.caller;
while (c) {
ev = c.arguments[0];
if (ev && Event == ev.constructor) {
break;
}
c = c.caller;
}
}
return ev;
}
};
十一、事件的执行顺序
参考文章,讲的很清楚
先看两个问题:
一个DOM元素绑定两个事件,一个冒泡,一个捕获,则事件会执行多少次,执行顺序如何。
事件捕获和冒泡,顺序,如果一个元素的冒泡事件定义在捕获之前会发生什么
总结结论
绑定在被点击元素的事件是按照代码顺序发生,其他元素通过冒泡或者捕获“感知”的事件,按照W3C的标准,先发生捕获事件,后发生冒泡事件。所有事件的顺序是:其他元素捕获阶段事件 -> 本元素代码顺序事件 -> 其他元素冒泡阶段事件 。
执行次数:绑定了几个事件便执行几次。
当每个元素绑定的事件不同,有冒泡有捕获时
首先,无论是冒泡事件还是捕获事件,元素都会先执行捕获阶段。
从上往下,如有捕获事件,则执行;一直向下到目标元素后,从目标元素开始向上执行冒泡元素,即第三个参数为true表示捕获阶段调用事件处理程序,如果是false则是冒泡阶段调用事件处理程序。(在向上执行过程中,已经执行过的捕获事件不再执行,只执行冒泡事件。)
<div id='one'>
<div id='two'>
<div id='three'>
<div id='four'>
div>
div>
div>
div>
<script type='text/javascript'>
var one=document.getElementById('one');
var two=document.getElementById('two');
var three=document.getElementById('three');
var four=document.getElementById('four');
one.addEventListener('click',function(){
alert('one');
},true); //捕获
two.addEventListener('click',function(){
alert('two');
},false); //冒泡
three.addEventListener('click',function(){
alert('three');
},true); //捕获
four.addEventListener('click',function(){
alert('four');
},false); //冒泡
script>
从根元素向目标元素向下判断执行,和目标元素本身的事件类型没有关系,根元素捕获—–>目标元素——>冒泡到根元素
此时点击four元素,最终执行结果为:one three four two
点击three元素,执行结果为:one three two
当一个元素绑定两个事件,一个冒泡,一个捕获
如果点击元素有两个事件,按代码的顺序执行,其他元素先捕获后冒泡
如果点击的是其他元素,则有两个事件的元素先捕获后冒泡,与代码顺序无关
one.addEventListener('click',function(){
alert('one');
},true);
two.addEventListener('click',function(){
alert('two,bubble');
},false);
two.addEventListener('click',function(){
alert('two,capture');
},true);
three.addEventListener('click',function(){
alert('three,bubble');
},true);
four.addEventListener('click',function(){
alert('four');
},true);
1、如果two为目标元素,目标元素的事情按顺序执行,而其他元素根据W3C的标准执行,即先捕获
后冒泡。
点击two执行结果:one(因为是two的父元素支持捕获事件所以先执行) two,bubble
two,capture(顺序执行,注意逗号不是间隔,是输出内容。)
2、如果目标元素不是two,则two的两个事件按先捕获后冒泡触发执行,也就是跟前面讨论的执行
过程是一样的,只不过两个事件都绑定在同一个DOM元素上。
点击three执行结果:one two,capture three,bubble two,bubble