javasciprt事件中有兩個很重要的特性:事件冒泡 以及目标元素 。
事件冒泡: 當一個元素上的事件被觸發的時候,比如說滑鼠點選了一個按鈕,同樣的事件将會在那個元素的所有祖先元素中被觸發。這一過程被稱為事件冒泡;這個事件從原始元素開始一直冒泡到dom樹的最上層。
目标元素: 任何一個事件的目标元素都是最開始的那個元素,在我們的這個例子中也就是按鈕,并且它在我們的元素對象中以屬性的形式出現。使用事件代理的話我們可以把事件處理器添加到一個元素上,等待一個事件從它的子級元素裡冒泡上來,并且可以很友善地得知這個事件是從哪個元素開始的。
事件的冒泡和捕獲
捕獲是從上級元素到下級元素,冒泡是從下級元素到上級元素.
在ie中,每個元素和window對象都有兩個方法:attachevent()和detachevent()。attachevent()用來給一個事件附加事件處理函數。而detachevent()用來将事件處理函數分離出來。eg.

var fnclick = function() {
alert(“clicked!”);
}
var odiv = document.getelementbyid(“div1”);
odiv.attachevent(“onclick”, fnclick);
odiv.detachevent(“onclick”, fnclick);
事件的冒泡有什麼好處呢?
想象一下現在我們有一個10列、100行的html表格,你希望在使用者點選表格中的某一單元格的時候做點什麼。比如說我有一次就需要讓表格中的每一個單元格在被點選的時候變成可編輯狀态。如果把事件處理器加到這1000個單元格會産生一個很大的性能問題,并且有可能導緻記憶體洩露甚至是浏覽器的崩潰。相反地,使用事件代理的話,你隻需要把一個事件處理器添加到table元素上就可以了,這個函數可以把點選事件給截下來,并且判斷出是哪個單元格被點選了。
代碼很簡單,我們所要關心的隻是如何檢測目标元素而已。比方說我們有一個table元素,id是“report”,我們為這個表格添加一個事件處理器以調用editcell函數。editcell函數需要判斷出傳到table來的事件的目标元素。考慮到我們要寫的幾個函數中都有可能用到這一功能,是以我們把它單獨放到一個名為geteventtarget的函數中:

function geteventtarget(e) {
e = e || window.event;
return e.target || e.srcelement;
e這個變量表示的是一個事件對象,我們隻需要寫一點點跨浏覽器的代碼來傳回目标元素, 在ie裡目标元素放在srcelemtn屬性或event.toelement 屬性 中,而在其它浏覽器裡則是target或event.relatedtarget 屬性。
接下來就是editcell函數了,這個函數調用到了geteventtarget函數。一旦我們得到了目标元素之後,剩下的事情就是看看它是否是我們所需要的那個元素了。

function editcell(e) {
var target = geteventtarget(e);
if(target.tagname.tolowercase() === 'td') {
// do something with the cell
}
}
在editcell函數中,我們通過檢查目标元素标簽名稱的方法來确定它是否是一個表格的單元格。這種檢查也許過于簡單了點;如果它是這個目标元素單元格裡的另一個元素呢?我們需要為代碼做一點小小的修改以便于其找出父級的td元素。如果說有些單元格不需要被編輯怎麼辦呢?此種情況下我們可以為那些不可編輯的單元格添加一個指定的樣式名稱,然後在把單元格變成可編輯狀态之前先檢查它是否不包含那個樣式名稱。選擇總是多樣化的,你隻需找到适合你應用程式的那一種。
事件冒泡的優點和缺點:
1.那些需要建立的以及駐留在記憶體中的事件處理器少了。
這是很重要的一點,這樣我們就提高了性能,并降低了崩潰的風險。
2.在dom更新後無須重新綁定事件處理器了。
如果你的頁面是動态生成的,比如說通過ajax,你不再需要在元素被載入或者解除安裝的時候來添加或者删除事件處理器了。
潛在的問題也許并不那麼明顯,但是一旦你注意到這些問題,你就可以輕松地避免它們: 你的事件管理代碼有成為性能瓶頸的風險,是以盡量使它能夠短小精悍。
不是所有的事件都能冒泡
blur、focus、load和unload不能像其它事件一樣冒泡。事實上blur和focus可以用事件捕獲而非事件冒泡的方法獲得(在ie之外的其它浏覽器中)。
需要注意的是:
如果你的代碼處理mousemove事件的話你遇上性能瓶頸的風險可就大了,因為mousemove事件觸發非常頻繁。而mouseout則因為其怪異的表現而變得很難用事件代理來管理。
如何避免事件冒泡:
1.方法

<!doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>js中的事件冒泡</title>
<script type="text/javascript"><!--
function clicktr()
{
alert("tr");
function clicktd()
alert("td");
//如果不加下面的代碼點選先會彈出td然後彈出tr,原因是html是對象結構當點選aaa的時候(執行),會冒泡到tr-->table-->body->document->window,當用event.cancelbubble=true的時候就說明阻止該冒泡行為
event.cancelbubble=true;
// --></script>
</head>
<body>
<div style="background-color:azure;" mce_style="background-color:azure;">目的當點選bbb的時候彈出tr,當點選aaa的時候彈出td</div>
<table>
<tr onclick="clicktr();">
<td onclick="clicktd();">aaa</td>
<td>bbb</td>
</tr>
</table>
</body>
</html>
2.方法
在ie下解決問題很簡單,用onmouseenter、onmouseleave 來代替onmouseover、onmouseout就行了,他們的作用基本相同,前者不會發生冒泡。但是firefox下沒有這兩個事件.
3.方法:
window.event.cancelbubble = true (ie) event.stoppropagation() event.preventdefault() (firefox)
<a href="http://www.allenle.com/archives/1882.html">阻止jquery事件冒泡</a>
jquery.event提供了一個非常簡單的方法來阻止事件冒泡:event.stoppropagation();

$("p").click( function (event){
event.stoppropagation(); // do something
})

$("p").live( "click" , function (){$( this ).after( "another paragraph!" );
return false ;
});

<html>
<body>
<table border="1" width="26%" id="tablea" onclick="alert('點選了tablea')">
<tr onclick="tablea_rowa_click()">
<td width="106">一般</td>
</tr>
<tr id="p">
<td width="106">阻止消息上傳</td>
</table>
</body>
<script language="javascript" src="jquery.js"></script>
<script language="javascript">
function tablea_rowa_click(){
alert('點選了tablea的rowa');
}
$("#p").click(function(event){
alert('點選了tablea的rowb');
event.stoppropagation();
});
</script>
在大多數情況下,為事件處理函數傳回false,可以防止預設的事件行為.例如,預設情況下點選一個<a>元素,頁面會跳轉到該元素href屬性指定的頁.return false 就相當于終止符,return true 就相當于執行符。在js中return false的作用一般是用來取消預設動作的。
比如你單擊一個連結除了觸發你的onclick時間(如果你指定的話)以外還要觸發一個預設事件就是執行頁面的跳轉。是以如果你想取消對象的預設動作就可以return false比如:
<input type="submit" onclick="submitaction(); return false;" />
submitaction 方法裡面有送出表單的動作。如果不加 return false,在執行完 submitaction 之後,submit 按鈕還會繼續執行它的預設事件,就會再次送出表單。這可能就是很多錯誤的根源。
多個alert同時彈出,解決

if(1){
alert("請選擇公司所在地區!");
return false;
阿斯蒂芬撒