JavaScript 瀏覽器事件解析
JavaScript、瀏覽器、事件之間的關係
JavaScript 程式採用了非同步事件驅動程式設計(Event-driven programming)模型,維基百科對它的解釋是:
事件驅動程式設計(英語:Event-driven programming)是一種電腦程式設計模型。這種模型的程式執行流程是由使用者的動作(如滑鼠的按鍵,鍵盤的按鍵動作)或者是由其他程式的訊息來決定的。相對於批處理程式設計(batch programming)而言,程式執行的流程是由程式設計師來決定。批量的程式設計在初級程式設計教學課程上是一種方式。然而,事件驅動程式設計這種設計模型是在互動程式(Interactive program)的情況下孕育而生的
簡頁言之,在 web 前端程式設計裡面 JavaScript 通過瀏覽器提供的事件模型 API 和使用者互動,接收使用者的輸入
由於使用者的行為是不確定的,也就是說不知道使用者什麼時候發生點選、滾動這些動作。這種場景是傳統的同步程式設計模型沒法解決的,因為你不可能等使用者操作完了才執行後面的程式碼
比如我們在 Python 裡面呼叫接收使用者輸入的方法 raw_input()
後終端就會一直等待使用者的輸入,直到輸入完成才會執行後面的程式碼邏輯。但是在下面這段 NodeJS 程式碼中,接收使用者輸入的方法 process.stdin.read
是在一個事件中呼叫的。後面的程式碼不會被阻塞(blocked)
1234567891011121314 | 'use strict';process.stdin.on('readable',()=>{varchunk=process.stdin.read();if(chunk!==null){process.stdout.write(`Async output data:${chunk}`);}});process.stdin.on('end',()=>{process.stdout.write('end');});console.log('Will not be blocked'); |
事件驅動程式模型基本的實現原理基本上都是使用 事件迴圈(Event Loop),這部分內容涉及瀏覽器事件模型、回撥原理,有興趣的去看連結裡面的視訊學習下
需要說明的是在客戶端 JavaScript 中像 setTimeout, XMLHTTPRequest 這類 API 並不是 JavaScript 語言本身就有的。而是 JavaScript 的宿主環境(在客戶端 JavaScript 中就是瀏覽器),同樣像 DOM、BOM、Event API 都是瀏覽器提供的
事件繫結的方法
DOM 元素行內繫結
直接在 DOM 元素上通過設定 on + eventType
來繫結事件處理程式
1 | <a href="#none"onclick="alert('clicked.')">點選我</a> |
這種繫結方法是最原始的,有兩個缺點:
1 事件處理程式和 HTML 結構混雜在一起
早期在結構、樣式、表現分離的時代很忌諱這一點。現在看來在很多 MVX 框架中將事件繫結和 DOM 結構放在一起處理,這樣似乎更方便維護(不用來回切換 HTML,JavaScript 檔案),而且也符合可預見(predictable)性的規則
2 名稱空間衝突
因為 onclick
中的 JavaScript 程式碼片段執行環境是全域性作用域。然而在 JavaScript 語言中並沒有相關的名稱空間特性。所以就很容易造成名稱空間的衝突,非要用這種方法繫結事件的話只能用物件來做一些封裝
古老的繫結方法
使用 DOM Element 上面的 on + eventType
屬性 API
123456 | <a href="#none"id="button">click me</a><script>varel=getElementById('button');el.onclick=function(){alert('button clicked.')};el.onclick=function(){alert('button clicked (Rewrite event handler before).')};</script> |
這種方法也有一個缺點,因為屬性賦值會覆蓋原值的。所以無法繫結 多個 事件處理函式,如果我們要註冊多個 onload 事件處理程式的話就得自己封裝一個方法來防止這種事情發生,下面這個例子可以解決這個問題
JavaScript12345678910111213141516 | <script>functionaddLoadEvent(fn){varoldonLoad=window.onload;if(typeofoldonLoad!=='function'){window.onload=fn;}else{window.onload=function(){oldonLoad();fn();}}}addLoadEvent(function(){alert('onload 1')});addLoadEvent(function(){alert('onload 2')});</script> |
注意這只是個示例,生產環境很少會用到。一般用 DOM Ready 就可以了,因為 JavaScript 的執行通常不用等到頁面資源全部載入完,DOM 載入完就可以了
現代/標準的繫結方法
標準的繫結方法有兩種,addEventListener
和 attachEvent
前者是標準瀏覽器支援的 API,後者是 IE 8 以下瀏覽器支援的 API。通常需要我們做個相容封裝
123456789101112 | <script>functionaddEvent(target,type,handler){if(target.addEventListener){target.addEventListener(type,handler,false);}else{target.attachEvent('on'+type,handler)}}addEvent(document,'click',function(){alert(this===document)});addEvent(document,'click',function(){alert(this===document)});</script> |
上面的例子在 IE 8 以下和標準瀏覽器的效果是不一樣的,問題就在於 addEventListener
中的事件回撥函式中的 this 指向元素(target)本身,而 attachEvent
則指向 window
為了修復這個問題上面的 attachEvent 可以做一點小調整讓其保持和 addEventListener
的效果一樣,不過這樣的話註冊的 handler 就是個匿名函式,無法移除!
12345678910111213 | <script>functionaddEvent(target,type,handler){if(target.addEventListener){target.addEventListener(type,handler,false);}else{target.attachEvent('on'+type,function(){returnhandler.call(target)});}}addEvent(document,'click',function(){alert(this===document)});</script> |
當上面這幾種情況同時出現的時候就比較有意思了,可以試試下面這段程式碼的你輸出
XHTML12345678 | <a href="javascript:alert(1)"onclick="alert(2)"id="link">click me</a><script>varlink=document.getElementById('link');link.onclick=function(){alert(3);}$('#link').bind('click',function(){alert(4);});$('#link').bind('click',function(){alert(5);});</script> |
正確的結果應該是 3,4,5,1
,根據結果我們可以得出以下結論:
- 連結上的 href 偽 javascript 協議相當於在瀏覽器位址列執行了一段 JavaScript 程式碼,連結如果是這種格式,點選的時候相當於執行了這段 JavaScript 指令碼
- 行內的事件繫結和元素呼叫 onclick 繫結事件會覆蓋
- 使用 jQuery(內部使用標準事件註冊 API)可以繫結多個事件處理程式
事件冒泡
大部分事件會沿著事件觸發的目標元素往上傳播。比如:body>div>p>span
如果他們都註冊了點選事件,那麼在 span 元素上觸發點選事件後 p,div,body 各自的點選事件也會按順序觸發
事件冒泡是可以被停止的,下面這個函式封閉了停止事件冒泡的方法:
JavaScript123456789101112131415 | <script>functionstopPropagation(event){event=event||window.event;if(event.stopPropagation){event.stopPropagation()}else{// IEevent.cancelBubble=true}}addEvent('ele','click',function(e){// click handlerstopPropagation(e);});</script> |
事件物件
標準瀏覽器中在事件處理程式被呼叫時 事件物件 會通過引數傳遞給處理程式,IE 8 及以下瀏覽器中事件物件可以通過全域性的 window.event
來訪問。比如我們要獲取當前點選的 DOM Element
123456789101112131415 | <script>addEvent(document,'click',function(event){// IE 8 以下 => undefinedconsole.log(event);});addEvent(document,'click',function(event){event=event||window.event;// 標準瀏覽器 => [object HTMLHtmlElement]// IE 8 以下 => undefinedconsole.log(event.target);vartarget=event.target||event.srcElement;console.log(target.tagName);});</script> |
事件代理
有時候我們需要給 不存在的(可能將來會有)的一段 DOM 元素繫結事件,比如給一段 Ajax 請求完成後渲染的 DOM 節點繫結事件。一般繫結的邏輯會在渲染前執行,繫結的時候找不到元素所以並不能成功,當然你也可以把繫結事件的程式碼放在 Ajax 請求之後。這樣做在一些事件邏輯簡單的應用裡面沒問題,但是會加重資料渲染邏輯和事件處理的邏輯耦合。一但事件處理程式特別多的時候,我們通常建議把事件的邏輯和其它程式碼邏輯分離,這樣方便維護。
為了解決這個問題,我們通常使用事件代理/委託(Event Delegation )。而且通常來說使用 事件代理的效能會比單獨繫結事件高 很多,我們來看個例子
XHTML1234567 | <ul id="list"><li id="item-1">item1</li><li id="item-2">item2</li><li id="item-3">item3</li><li id="item-4">item4</li><li id="item-5">item5</li></ul> |
假如 ul
中的 HTML 是 Ajax 非同步插入的,通常我們的做法是 插入完成後遍歷每個 li 繫結事件處理程式
12345相關推薦JavaScript 瀏覽器事件解析JavaScript、瀏覽器、事件之間的關係 JavaScript 程式採用了非同步事件驅動程式設計(Event-driven programming)模型,維基百科對它的解釋是: 事件驅動程式設計(英語:Event-driven programming)是一種電腦程式設計模型 javascript阻止事件冒泡和瀏覽器的默認行為pre stop key else can put 事件冒泡 prop top 1.阻止事件冒泡,使成為捕獲型事件觸發機制. 1 function stopBubble(e) { 2 //如果提供了事件對象,則這是一個非IE瀏覽器 3 if ( e && JavaScript瀏覽器解析原理首先,JavaScript的特點是: 1. 跨平臺 可以再不同的作業系統上執行。 2. 弱型別 與之相對的是強型別 強型別:在定義變數的時候,需要將變數的資料型別表明。例如:Java 弱型別:定義變數的時候不需要定義資料型別,資料型別根據變數值來確定。例如: 移動裝置、手機瀏覽器Javascript滑動事件程式碼以下經過本人測試成功。 測試平臺:三星S5830I 作業系統:Android 2.3.6 瀏覽器:UC瀏覽器 HTML標準:HTML5 測試了三個事件:touchstart、touchmove 和 touchend,並獲取了觸控時觸點在頁面上的座標,根據座標進行了左右滑動 瀏覽器常用事件解析之前寫過一篇瀏覽器事件的相關操作和事件執行的原理——JavaScript瀏覽器事件解析。這一篇主要寫一些常用的事件及一些可能的坑。 表單事件 鍵盤事件 當 <input>, <textarea> 的值發生變化時觸發。此外,開 javascript打造跨瀏覽器事件處理機制:詳解由於瀏覽器相容的複雜性.打造一個較優的跨瀏覽器事件處理函式.不是件容易的事情.各大類庫也都通過了種種方案去抽象一個龐大的事件機制. 使用類庫可以比較容易的解決相容性問題.但這背後的機理又是如何呢? 下面我們就一點點鋪開來講. element.add [瀏覽器事件循環] javaScript事件循環 EventLoop發現 按順序 總結 維數 完成後 js調用 observer 特殊 基本上 前言 Event Loop即事件循環,是指瀏覽器或Node的一種解決javaScript單線程運行時不會阻塞的一種機制,也就是我們經常使用異步的原理。 先熟悉基本概念 【堆Heap】 堆是一種數據 js window事件解析(轉載)slow disable forward 建立 多選 1.0 參數 小程序 距離 js-window對象的方法和屬性資料 hxpd 發表於 2007-05-08 21:58:18 熟練window對象的open、close、alert、confirm、prompt、setT JavaScript筆記——事件跟著 bsp ava eset 窗口 輸入框 put cli 交互 事件一般是用於瀏覽器和用戶操作進行交互。最早是 IE 和 Netscape Navigator 中出現, 作為分擔服務器端運算負載的一種手段。直到幾乎所有的瀏覽器都支持事件處理。而 DOM2 級規範開始嘗試 瀏覽器的解析和執行過程們的 由於 繼續 動畫 table 就會 內嵌 cnblogs 內嵌腳本 當瀏覽器獲得一個html文件時,會“自上而下”加載,並在加載過程中進行解析渲染。 解析: 1. 瀏覽器會將HTML解析成一個DOM樹(display:none,visibility:hidden)。 JavaScript-onerror事件:圖片加載失敗後不顯示mage function title 存在 fault splay pan hive javascrip HTML: <img src="http://www.mazey.net/images/upload/image/20170518/14951221981806 javascript-瀏覽器消息提醒練手 index 詳細 nts tts miss 了解 .com asc 如何讓用戶在瀏覽器最小化的狀態下也能及時的收到消息提醒呢? 這個問題作為webRd是要正面面對的. 大約可分兩種場景:一種是類似桌面通知的形式還有一種是類似QQ提醒(在系統任務欄閃爍隨後高亮);接下來 JavaScript響應事件onchange 表單 例如 單擊事件 處理器 什麽事 英文 lur 按鍵 事件:發生了某一件事情。 例如: onClick鼠標單擊,當你單擊的時候發生什麽事情。 1.onBlur焦點離開事件 2.onChange用戶修改了值正要離開事件 3.onClick鼠標單擊事件 4 Javascript - ExtJs - 事件events gif gety src button 簡單 顯示 mouseover java 事件(ExtJs Event) Ext.Util.observable類 Ext.Util.observable是一個接口,為Ext組件的事件提供了支持,組件的事件不同於傳 JavaScript中事件的target屬性button name 點擊事件 .html hasclass alert -c color min target 事件屬性可返回事件的目標節點(哪個 DOM 元素觸發了該事件),如生成事件的元素、文檔或窗口。 語法:event.target <html> & Javascript----input事件實現動態監聽textarea內容變化span oninput idt ava ntb ima property onchange pre 1、代碼 <!DOCTYPE html> <html> <head> <title>textarea輸入文字監聽 JavaScript之事件概念和監聽事件scrip isp doctype utf itl 技術分享 創建 img ret 1、事件的概念: JavaScript使我們有能力創建動態頁面,網頁中的每一個元素都可以產生某些觸發JavaScript函數的事件。我們可以認為事件是可以被JavaScript偵測到的一種行 javascript 瀏覽器定位his fail 1.5 doc int jquery margin point hidden <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=" C#事件の事件解析intern 處理機 信息 nta 語句 args handler poi pri 事件(event)是基於windows消息處理機制的類,封裝的更好,讓開發者無須知道底層的消息處理機制,就可以開發出強大的基於事件的應用程序來。委托(delegate)委托可以理解成為函數指 javascript-詞法分析解析utf -c head 詞法分析 img style utf-8 doc rip <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> |