1. 事件冒泡##
由內而外的事件傳播(從屏幕裡飛出來一支箭的感覺)
2. 事件捕獲##
由表及裡的事件傳播(力透紙背的感覺)
3. DOM 事件流(DOM2 級)##
事件捕獲階段 -> 處於目標階段 -> 事件冒泡階段(拿根針從屏幕紮進去,縫衣服的感覺)
事件捕獲是從 DOM 樹根到葉子的事件傳播,所以可以在靠近根的位置捕獲(event.stopPropagation)事件,讓葉子收不到事件信號
事件冒泡是從葉子到根的原路返回過程,所以可以在靠近根的位置集中處理(event.target)葉子的事件,也就是所謂的事件委託,集中處理可以避免給多個葉子綁定事件處理器,拉低響應速度
處於目標階段只是規範要求,瀏覽器沒怎麼支持
注意:[IE9+] 支持事件捕獲,事件冒泡是全瀏覽器支持的
4. 添加事件處理器的幾種方式##
- HTML:on 事件名 = strCode 事件處理函數可直接訪問的属性 = 全局属性 + 元素所在 form 中的属性 + 元素本身的属性
自動的作用域擴展方式相當於:
function(){
with(document){//全局属性
with(this.form){//表單属性
with(this){
//本身属性
}
}
}
}
事件處理函數可以直接訪問這麼多属性,所以,可以這樣做:
<form method="post">
<input type="text" name="user_name" value="">
<input type="button" value="獲取用戶名" onclick="alert(user_name.value)">
</form>
2. DOM0 級:elem.on 事件名 = functionName/null;
以這種方式添加的事件處理器在冒泡階段執行,可直接訪問的属性 = 全局属性 + 元素本身的属性
- DOM2 級:(現代瀏覽器支持的)elem.add/removeEventListener(事件名,functionName, false/true);
false 表示在事件冒泡階段添加,true 表示在事件捕獲階段添加。可直接訪問的属性同上
- [IE8-]:elem.attach/detachEvent(on 事件名(on 不能丟了), functionName);
可直接訪問的属性只有全局属性,而且對同一事件添加的多個處理器中,最後添加的最先執行,與 DOM2 級標準相反
P.S. [IE8-] 只支持事件冒泡,所以沒有第三個參數,默認(也只能是)在事件冒泡階段添加
5. 事件對象有什麼用?##
btn.onclick = function(event){
//event.target; 獲取事件源
//event.preventDefault(); 取消默認行為,比如鏈接的跳轉行為
//event.stopPropagation(); 阻斷事件傳播
//還有一些不常用的
}
注意:上面代碼並不是全瀏覽器兼容的,事件對象的属性也不完整,更多信息請查看 [JS 原生事件處理(跨瀏覽器)](/articles/js 原生事件處理(跨瀏覽器)/)
6. 事件分類##
-
UI 事件
-
焦點事件
-
鼠標事件
-
滾輪事件
-
文本事件
-
鍵盤事件
-
合成事件(用 IME 輸入)
-
變動事件(DOM 結構更新)
-
HTML5 事件
-
設備事件(特定設備,比如遊戲機)
-
觸摸與手勢事件
7. 事件委託##
利用事件冒泡來減少事件處理器,以提升性能。甚至可以給 document 對象添加事件處理器,以求更短的交互準備時間(頁面元素與事件處理器建立連接需要時間)
事件委託的優點:
-
設置事件處理器需要時間更少,因為 DOM 訪問次數變少了
-
佔用內存空間更少,因為事件處理器變少了
-
交互準備時間變短了,因為頁面元素與事件處理器之間需要建立的連接變少了
-
頁面響應速度變快了,因為頁面元素與事件處理器之間建立的連接變少了
8. 移除事件處理器的注意事項##
在目標元素被從 DOM 樹中刪除前應該手動移除與之綁定的事件處理器,避免失效的事件處理器佔用內存
在頁面 unload 之前,最好手動移除頁面中的所有事件處理器,因為 [IE8-] 在 unload 頁面時,事件處理器會滯留在內存中。可以在 unload 事件處理器中移除
移除事件處理器的實質是斷開頁面元素與事件處理器之間的連接
9. 模擬事件的方式(即代碼觸發指定事件)##
-
創建 event 對象
-
初始化 event 對象的各項属性
-
觸發事件
注意:[IE8-] 的實現與 DOM 規範不同;DOM3 級才能完美模擬鍵盤事件
10. 常識及性能優化策略##
-
只有在需要攔截別的事件時才把事件處理器添加在捕獲階段,因為 [IE8-] 不支持事件捕獲
-
對於動態創建的 img 元素,只要設置了 src 属性就會開始下載相關內容,而不是在新元素被插入 DOM 樹後才開始
-
對於動態創建的 script 元素,只有插入 DOM 樹後才會開始下載
-
對於動態創建的 link 元素(用來加載外部樣式),只有插入到head 部分才能保證瀏覽器表現一致,而且外部樣式默認是異步加載的
-
用 in 操作符來檢測事件支持,例如:
if('onload' in elem){ //do sth } -
hover, mouseover, mouseout, mouseenter, mouseleave 的區別是什麼?
- hover 是 CSS 偽類,鼠標進入並處於目標元素中時觸發;
- mouseover 是鼠標事件,鼠標進入目標元素時觸發,得到了瀏覽器廣泛支持。相當於 mouseenter,但 mouseenter 沒有得到完全支持;
- mouseout 與 mouseover 相反,mouseleave 與 mouseenter 相反,後者沒有得到完全支持;
- 本機測試:FF 和 IE 全支持,Chrome 不支持 enter/leave。
-
事件委託是最重要的優化策略,當然,委託也不是完美的,委託會導致邏輯粘連,比如極端的情況,給 document 對象添加一個事件處理器就够了,但那將是一個很大只的函數。。。所以,應該在合適的地方盡量用委託
-
適時移除過期的時間處理器可以減少內存佔用,這是空間方面的優化策略
暫無評論,快來發表你的看法吧