javascript理解之事件详解

事件冒泡与捕获

事件冒泡与捕获

事件冒泡的好处

因为事件具有冒泡机制,因此我们可以利用冒泡的原理,把事件加到父级上,触发执行效果。这样做的好处当然就是提高性能了,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<head lang="en">
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
window.onload = function () {
var aUl = document.getElementsById("bubble");
var aLi = aUl.getElementsByTagName("li");

for(var i = 0;i<aLi.length;i++){
aLi[i].onmouseover = function () {
this.style.backgroundColor = "blue";
};
ali[i].onmouseout = function () {
this.style.backgroundColor = "";
}
}
};
</script>
</head>
<body>
<div>
<ul id = "bubble">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</div>
</body>

这样我们就可以做到li上面添加鼠标事件。但是如果说我们可能有很多个li用for循环的话就比较影响性能。

下面我们可以用事件委托的方式来实现这样的效果。html不变:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<script type="text/javascript">
window.onload = function () {
var aUl = document.getElementsById("bubble");
var aLi = aUl.getElementsByTagName("li");

//不管在哪个事件中,只要你操作的那个元素就是事件源。
// ie:window.event.srcElement
// 标准下:event.target
aUl.onmouseover = function (ev) {
var ev = ev || window.event;
var target = ev.target || ev.srcElement;

if(target.nodeName.toLowerCase() == "li"){
target.style.background = "blue";
}
};
aUl.onmouseout = function (ev) {
var ev = ev || window.event;
var target = ev.target || ev.srcElement;

if(target.nodeName.toLowerCase() = "li"){
target.style.background = "";
}
}
};
</script>

那么,如何阻止事件的冒泡呢,看下面一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div onclick="showMsg(this,event)" id="outSide" style="width:100px; height:100px; background:#000; padding:50px">
<div onclick="showMsg(this,event)" id="inSide" style="width:100px; height:100px; background:#CCC"></div>
</div>
<script type="text/javascript">
//阻止事件冒泡后,你点击灰色盒子,整个过程只弹一次对话框了(注意与默认情况对比)
function showMsg(obj,e)
{
alert(obj.id);
stopBubble(e)
}

//阻止事件冒泡函数
function stopBubble(e)
{
if (e && e.stopPropagation)
e.stopPropagation()
else
window.event.cancelBubble=true
}
</script>

事件对象

在触发DOM上的某个事件时,会产生一个事件对象event,这个对象包含着所有与事件相关的信息。包括导致事件的元素、事件的类型以及其他与特定事件相关的信息。event对象会被作为第一个参数传递给事件监听的回调函数。

我们可以通过这个event对象来获取到大量当前事件相关的信息:

  1. type (String) — 事件的名称
  2. target (node) — 事件起源的DOM节点
  3. currentTarget?(node) — 当前回调函数被触发的DOM节点(后面会做比较详细的介绍)
  4. bubbles (boolean) — 指明这个事件是否是一个冒泡事件(接下来会做解释)
  5. preventDefault(function) — 这个方法将阻止浏览器中用户代理对当前事件的相关默认行为被触发。比如阻止a元素的click事件加载一个新的页面
  6. cancelable (boolean) — 这个变量指明这个事件的默认行为是否可以通过调用event.preventDefault来阻止。
  7. stopPropagation (function) — 取消事件的进一步捕获或冒泡,bubbles为true使用这个方法
  8. eventPhase:返回一个数字,表示事件目前所处的阶段,0为事件开始从DOM表层向目标元素传播,1为捕获阶段,2为事件到达目标元素,3为冒泡阶段。

此外,事件对象还可能拥有很多其他的属性,但是他们都是针对特定的event的。比如,鼠标事件包含clientX和clientY属性来表明鼠标在当前视窗的位置。

另外,stopPropagation()方法用于立即停止事件在DOM中的传播,即取消进一步的事件冒泡或捕获。

1
2
3
4
5
6
7
8
9
10
var btn = document.getElementById('myDiv');
btn.onclick = function (event) {
alert("clicked");
event.stopPropagation();
};

//避免触发在document.body上的事件处理程序
document.body.onclick = function (event) {
alert("Body clicked");
};

只有在事件处理程序执行期间,event对象才会存在,一旦事件处理程序执行完毕,event对象就会自动销毁。

click事件

当用户点击以后,event对象会包含以下属性。

  1. pageX,pageY:点击位置相对于html元素的坐标,单位为像素。
  2. clientX,clientY:点击位置相对于视口(viewport)的坐标,单位为像素。
  3. screenX,screenY:点击位置相对于设备显示屏幕的坐标,单位为设备硬件的像素

焦点事件

焦点事件会在页面元素获得或失去焦点时触发,有以下4个焦点事件:

  1. blur:元素失去焦点时触发,该事件不冒泡
  2. focus:元素获得焦点时触发。不冒泡
  3. focusin:元素获得焦点时触发,冒泡
  4. focusout:元素失去焦点时触发,冒泡

鼠标事件

  1. click:当用户点击鼠标主键通常是指鼠标左键或按回车键时触发。

  2. dbclick:用户双击鼠标时触发

  3. mousedown:当用户按下鼠标任意一个键都会触发,这个事件是不能够通过键盘触发的。

  4. mousemove:当鼠标在某元素周围移动时重复触发,该事件不能通过键盘事件触发。

  5. mouseout:当鼠标离开元素时触发,这个事件不能通过键盘触发。

  6. mouseover:当鼠标进入元素时触发,这个事件不能够通过键盘触发。

  7. mouseenter:类似“mouseover”,但不冒泡,而且当光标移到后代元素上不会触发。

  8. mouseleave:类似“mouseout”,但不冒泡。在元素上方是不触发。

  9. mouseup:当用户释放鼠标按键时触发,不能够通过键盘触发。

文章参考:http://segmentfault.com/a/1190000002174034