最近在跟学姐还有一群小伙伴们们给老师做一个项目,第一次做真实的项目而且是特别正式的那种,最我这种菜鸟来说简直了,各种问题都出来了,以前想不到的,甚至以前遇到的问题都跑出来了,最近发的博客可能都与解决这些问题有关,今天我来讲讲事件冒泡。
什么是事件?
事件表示一件事,既然有了这件事就肯定让它有实现的意义,这就引出了触发。事件触发往往是联系在一起的,是可以被 JavaScript 侦测到的行为。我们往往习惯给这个事件创建函数,通过函数来实现触发这个事件后的效果。在js库里有许多事件函数,你能想到的想不到的,各种各样。但是事件冒泡又是什么呢?
什么是事件冒泡?
事件冒泡是指从事件目标开始往上冒泡直到最顶层的目标即document标签。举个例子:有一个div标签里有一个p标签,二者都绑定了onclick事件,如果用户在p上触发了点击事件,而p也在div中也就相应的触发了div的点击事件,那么触发的顺序如何呢?就是从p开始触发,接着是它的父元素,如果有更多的标签都存在onclick事件,那么就逐层往上触发。有时候正是由于这个特性才会出现问题。
实例
有一个table表格,有三列内容,第一列保存科目,第二列成绩,第三列空白,但是表格的最后一行最后一列始终有一个增加按钮,点击增加按钮新增一行并且这个按钮只能在最后一行有。就是这个效果:
如有我这样写:
<!DOCTYPE html>
<html>
<head>
<title>事件冒泡</title>
<meta charset="utf-8">
</head>
<body>
<table>
<thead colspan="3">
<tr>
<td>科目</td>
<td>成绩</td>
<td></td>
</tr>
</thead>
<tbody>
<tr>
<td>C语言</td>
<td>99</td>
<td></td>
</tr>
<tr>
<td>高数</td>
<td>97</td>
<td></td>
</tr>
<tr>
<td>离散</td>
<td>94</td>
<td><input type="submit" value="增加" id="addBtn"></td>
</tr>
</tbody>
</table>
</body>
<script type="text/javascript">
(function(){
var btn = document.getElementById('addBtn');
btn.onclick = function()
{
var tbody = btn.parentNode.parentNode.parentNode;
var td = btn.parentNode;
var tr = document.createElement('tr');
td.innerHTML = "";
tr.innerHTML = '<td>英语</td>' +
'<td>83</td>' +
'<td><input type="submit" value="增加" id="addBtn"></td>';
tbody.appendChild(tr);
}
})();
</script>
</html>
然而这个方法并不行,第一次的确可以实现效果,但之后就不行了,原因很简单就是没有将点击事件绑定上去。对,我是有一个笨办法,可以新建很多td,然后给最后一个td绑定一个点击事件,但是如果td特别多呢,是不是显得代码愈加的繁琐了。因为上面的代码例子是给btn也就是那个button添加的点击事件,第一次点击后它就消失了,所以以后再也不会被触发这个事件了,所以我们就要想到给一个永远不变的元素添加点击事件,然后用来判断是否为addBtn这个元素,从而实现效果,这就是事件冒泡的原理。代码如下:
<!DOCTYPE html>
<html>
<head>
<title>事件冒泡</title>
<meta charset="utf-8">
</head>
<body>
<table>
<thead colspan="3">
<tr>
<td>科目</td>
<td>成绩</td>
<td></td>
</tr>
</thead>
<tbody>
<tr>
<td>C语言</td>
<td>99</td>
<td></td>
</tr>
<tr>
<td>高数</td>
<td>97</td>
<td></td>
</tr>
<tr>
<td>离散</td>
<td>94</td>
<td><input type="submit" value="增加" id="addBtn"></td>
</tr>
</tbody>
</table>
</body>
<script type="text/javascript">
(function(){
var tbody = document.getElementsByTagName('tbody')[0];
tbody.onclick = function(e){
var e = e||window.event;
if(e.target.id == "addBtn"){
var btn = document.getElementById('addBtn');
btn.parentNode.innerHTML = "";
var tr = document.createElement('tr');
tr.innerHTML = '<td>英语</td>' +
'<td>83</td>' +
'<td><input type="submit" value="增加" id="addBtn"></td>';
tbody.appendChild(tr);
}
}
})();
</script>
</html>
这下就完美的实现了效果,如图:
阻止事件冒泡
有需要事件冒泡的当然也有要阻止的情况了,比如上述的例子,我就想触发p标签的点击事件而不再触发它的父元素,这里有一个函数叫做stopPropagation(),这个函数我在第一次博客中就谈论到了,这里就不再研究了,相信原理也很简单的。