摘要:事件與節點每個瀏覽器事件處理器被注冊在上下文中。事件對象雖然目前為止我們忽略了它,事件處理器函數作為對象傳遞事件對象。若事件處理器不希望執行默認行為通常是因為已經處理了該事件,會調用事件對象的方法。
來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項目原文:Handling Events
譯者:飛龍
協議:CC BY-NC-SA 4.0
自豪地采用谷歌翻譯
部分參考了《JavaScript 編程精解(第 2 版)》
你對你的大腦擁有控制權,而不是外部事件。認識到這一點,你就找到了力量。
馬可·奧勒留,《沉思錄》
有些程序處理用戶的直接輸入,比如鼠標和鍵盤動作。這種輸入方式不是組織整齊的數據結構 - 它是一次一個地,實時地出現的,并且期望程序在發生時作出響應。
事件處理器想象一下,有一個接口,若想知道鍵盤上是否有一個鍵是否被按下,唯一的方法是讀取那個按鍵的當前狀態。為了能夠響應按鍵動作,你需要不斷讀取鍵盤狀態,以在按鍵被釋放之前捕捉到按下狀態。這種方法在執行時間密集計算時非常危險,因為你可能錯過按鍵事件。
一些原始機器可以像那樣處理輸入。有一種更進一步的方法,硬件或操作系統發現按鍵時間并將其放入隊列中。程序可以周期性地檢查隊列,等待新事件并在發現事件時進行響應。
當然,程序必須記得監視隊列,并經常做這種事,因為任何時候,按鍵被按下和程序發現事件之間都會使得軟件反應遲鈍。該方法被稱為輪詢。大多數程序員更希望避免這種方法。
一個更好的機制是,系統在發生事件時主動通知我們的代碼。瀏覽器實現了這種特性,支持我們將函數注冊為特定事件的處理器。
Click this document to activate the handler.
window綁定指向瀏覽器提供的內置對象。 它代表包含文檔的瀏覽器窗口。 調用它的addEventListener方法注冊第二個參數,以便在第一個參數描述的事件發生時調用它。
事件與 DOM 節點每個瀏覽器事件處理器被注冊在上下文中。在為整個窗口注冊處理器之前,我們在window對象上調用了addEventListener。 這種方法也可以在 DOM 元素和一些其他類型的對象上找到。 僅當事件發生在其注冊對象的上下文中時,才調用事件監聽器。
No handler here.
示例代碼中將處理器附加到按鈕節點上。因此,點擊按鈕時會觸發并執行處理器,而點擊文檔的其他部分則沒有反應。
向節點提供onclick屬性也有類似效果。這適用于大多數類型的事件 - 您可以為屬性附加處理器,屬性名稱為前面帶有on的事件名稱。
但是一個節點只能有一個onclick屬性,所以你只能用這種方式為每個節點注冊一個處理器。 addEventListener方法允許您添加任意數量的處理器,因此即使元素上已經存在另一個處理器,添加處理器也是安全的。
removeEventListener方法將刪除一個處理器,使用類似于addEventListener的參數調用。
賦予removeEventListener的函數必須是賦予addEventListener的完全相同的函數值。 因此,要注銷一個處理其,您需要為該函數提供一個名稱(在本例中為once),以便能夠將相同的函數值傳遞給這兩個方法。
事件對象雖然目前為止我們忽略了它,事件處理器函數作為對象傳遞:事件(Event)對象。這個對象持有事件的額外信息。例如,如果我們想知道哪個鼠標按鍵被按下,我們可以查看事件對象的which屬性。
存儲在各種類型事件對象中的信息是有差別的。隨后本章將會討論許多類型的事件。對象的type屬性一般持有一個字符串,表示事件(例如"click"和"mousedown")。
傳播對于大多數事件類型,在具有子節點的節點上注冊的處理器,也將接收發生在子節點中的事件。若點擊一個段落中的按鈕,段落的事件處理器也會收到點擊事件。
但若段落和按鈕都有事件處理器,則先執行最特殊的事件處理器(按鈕的事件處理器)。也就是說事件向外傳播,從觸發事件的節點到其父節點,最后直到文檔根節點。最后,當某個特定節點上注冊的所有事件處理器按其順序全部執行完畢后,窗口對象的事件處理器才有機會響應事件。
事件處理器任何時候都可以調用事件對象的stopPropagation方法,阻止事件進一步傳播。該方法有時很實用,例如,你將一個按鈕放在另一個可點擊元素中,但你不希望點擊該按鈕會激活外部元素的點擊行為。
下面的示例代碼將mousedown處理器注冊到按鈕和其外部的段落節點上。在按鈕上點擊鼠標右鍵,按鈕的處理器會調用stopPropagation,調度段落上的事件處理器執行。當點擊鼠標其他鍵時,兩個處理器都會執行。
A paragraph with a .
大多數事件對象都有target屬性,指的是事件來源節點。你可以根據該屬性防止無意中處理了傳播自其他節點的事件。
我們也可以使用target屬性來創建出特定類型事件的處理網絡。例如,如果一個節點中包含了很長的按鈕列表,比較方便的處理方式是在外部節點上注冊一個點擊事件處理器,并根據事件的target屬性來區分用戶按下了哪個按鈕,而不是為每個按鈕都注冊獨立的事件處理器。
默認動作
大多數事件都有與其關聯的默認動作。若點擊鏈接,就會跳轉到鏈接目標。若點擊向下的箭頭,瀏覽器會向下翻頁。若右擊鼠標,可以得到一個上下文菜單等。
對于大多數類型的事件,JavaScript 事件處理器會在默認行為發生之前調用。若事件處理器不希望執行默認行為(通常是因為已經處理了該事件),會調用preventDefault事件對象的方法。
你可以實現你自己的鍵盤快捷鍵或交互式菜單。你也可以干擾用戶期望的行為。例如,這里實現一個無法跳轉的鏈接。
MDN
除非你有非常充足的理由,否則不要這樣做。當預期的行為被打破時,使用你的頁面的人會感到不快。
在有些瀏覽器中,你完全無法攔截某些事件。比如在 Chrome 中,關閉鍵盤快捷鍵(CTRL-W或COMMAND-W)無法由 JavaScript 處理。
按鍵事件當按下鍵盤上的按鍵時,瀏覽器會觸發"keydown"事件。當松開按鍵時,會觸發"keyup"事件。
This page turns violet when you hold the V key.
盡管從keydown這個事件名上看應該是物理按鍵按下時觸發,但當持續按下某個按鍵時,會循環觸發該事件。有時,你想謹慎對待它。例如,如果您在按下某個按鍵時向 DOM 添加按鈕,并且在釋放按鍵時再次將其刪除,則可能會在按住某個按鍵的時間過長時,意外添加數百個按鈕。
該示例查看了事件對象的key屬性,來查看事件關于哪個鍵。 該屬性包含一個字符串,對于大多數鍵,它對應于按下該鍵時將鍵入的內容。 對于像Enter這樣的特殊鍵,它包含一個用于命名鍵的字符串(在本例中為"Enter")。 如果你按住一個鍵的同時按住Shift鍵,這也可能影響鍵的名稱 - "v"變為"V","1"可能變成"!",這是按下Shift-1鍵 在鍵盤上產生的東西。
諸如shift、ctrl、alt和meta(Mac 上的command)之類的修飾按鍵會像普通按鍵一樣產生事件。但在查找組合鍵時,你也可以查看鍵盤和鼠標事件的shiftKey、ctrlKey、altKey和metaKey屬性來判斷這些鍵是否被按下。
Press Ctrl-Space to continue.
按鍵事件發生的 DOM 節點取決于按下按鍵時具有焦點的元素。 大多數節點不能擁有焦點,除非你給他們一個tabindex屬性,但像鏈接,按鈕和表單字段可以。 我們將在第 18 章中回顧表單字段。 當沒有特別的焦點時,document.body充當按鍵事件的目標節點。
當用戶鍵入文本時,使用按鍵事件來確定正在鍵入的內容是有問題的。 某些平臺,尤其是 Android 手機上的虛擬鍵盤,不會觸發按鍵事件。 但即使你有一個老式鍵盤,某些類型的文本輸入也不能直接匹配按鍵,例如其腳本不適合鍵盤的人所使用的 IME(“輸入法編輯器”)軟件 ,其中組合多個熱鍵來創建字符。
要注意什么時候輸入了內容,每當用戶更改其內容時,可以鍵入的元素(例如和標簽)觸發"input"事件。為了獲得輸入的實際內容,最好直接從焦點字段中讀取它。 第 18 章將展示如何實現。
指針事件目前有兩種廣泛使用的方式,用于指向屏幕上的東西:鼠標(包括類似鼠標的設備,如觸摸板和軌跡球)和觸摸屏。 它們產生不同類型的事件。
鼠標點擊點擊鼠標按鍵會觸發一系列事件。"mousedown"事件和"mouseup"事件類似于"keydown"和"keyup"事件,當鼠標按鈕按下或釋放時觸發。當事件發生時,由鼠標指針下方的 DOM 節點觸發事件。
在mouseup事件后,包含鼠標按下與釋放的特定節點會觸發"click"事件。例如,如果我在一個段落上按下鼠標,移動到另一個段落上釋放鼠標,"click"事件會發生在包含這兩個段落的元素上。
若兩次點擊事件觸發時機接近,則在第二次點擊事件之后,也會觸發"dbclick"(雙擊,double-click)事件。
為了獲得鼠標事件觸發的精確信息,你可以查看事件中的clientX和clientY屬性,包含了事件相對于窗口左上角的坐標(以像素為單位)。或pageX和pageY,它們相對于整個文檔的左上角(當窗口被滾動時可能不同)。
下面的代碼實現了簡單的繪圖程序。每次點擊文檔時,會在鼠標指針下添加一個點。還有一個稍微優化的繪圖程序,請參見第 19 章。
鼠標移動
每次鼠標移動時都會觸發"mousemove"事件。該事件可用于跟蹤鼠標位置。當實現某些形式的鼠標拖拽功能時,該事件非常有用。
舉一個例子,下面的程序展示一條欄,并設置一個事件處理器,當向左拖動這個欄時,會使其變窄,若向右拖動則變寬。
Drag the bar to change its width:
請注意,mousemove處理器注冊在窗口對象上。即使鼠標在改變窗口尺寸時在欄外側移動,只要按住按鈕,我們仍然想要更新其大小。
釋放鼠標按鍵時,我們必須停止調整欄的大小。 為此,我們可以使用buttons屬性(注意復數形式),它告訴我們當前按下的按鍵。 當它為零時,沒有按下按鍵。 當按鍵被按住時,其值是這些按鍵的代碼總和 - 左鍵代碼為 1,右鍵為 2,中鍵為 4。 這樣,您可以通過獲取buttons的剩余值及其代碼,來檢查是否按下了給定按鍵。
請注意,這些代碼的順序與button使用的順序不同,中鍵位于右鍵之前。 如前所述,一致性并不是瀏覽器編程接口的強項。
觸摸事件我們使用的圖形瀏覽器的風格,是考慮到鼠標界面的情況下而設計的,那個時候觸摸屏非常罕見。 為了使網絡在早期的觸摸屏手機上“工作”,在某種程度上,這些設備的瀏覽器假裝觸摸事件是鼠標事件。 如果你點擊你的屏幕,你會得到"mousedown","mouseup"和"click"事件。
但是這種錯覺不是很健壯。 觸摸屏與鼠標的工作方式不同:它沒有多個按鈕,當手指不在屏幕上時不能跟蹤手指(來模擬"mousemove"),并且允許多個手指同時在屏幕上。
鼠標事件只涵蓋了簡單情況下的觸摸交互 - 如果您為按鈕添加"click"處理器,觸摸用戶仍然可以使用它。 但是像上一個示例中的可調整大小的欄在觸摸屏上不起作用。
觸摸交互觸發了特定的事件類型。 當手指開始觸摸屏幕時,您會看到"touchstart"事件。 當它在觸摸中移動時,觸發"touchmove"事件。 最后,當它停止觸摸屏幕時,您會看到"touchend"事件。
由于許多觸摸屏可以同時檢測多個手指,這些事件沒有與其關聯的一組坐標。 相反,它們的事件對象擁有touches屬性,它擁有一個類數組對象,每個對象都有自己的clientX,clientY,pageX和pageY屬性。
你可以這樣,在每個觸摸手指周圍顯示紅色圓圈。
Touch this page
您經常希望在觸摸事件處理器中調用preventDefault,來覆蓋瀏覽器的默認行為(可能包括在滑動時滾動頁面),并防止觸發鼠標事件,您也可能擁有它的處理器。
滾動事件每當元素滾動時,會觸發scroll事件。該事件用處極多,比如知道用戶當前查看的元素(禁用用戶視線以外的動畫,或向邪惡的指揮部發送監視報告),或展示一些滾動的跡象(通過高亮表格的部分內容,或顯示頁碼)。
以下示例在文檔上方繪制一個進度條,并在您向下滾動時更新它來填充:
將元素的position屬性指定為fixed時,其行為和absolute很像,但可以防止在文檔滾動時期跟著文檔一起滾動。其效果是讓我們的進度條呆在最頂上。 改變其寬度來指示當前進度。 在設置寬度時,我們使用%而不是px作為單位,使元素的大小相對于頁面寬度。
innerHeight全局綁定是窗口高度,我們必須要減去滾動條的高度。你點擊文檔底部的時候是無法繼續滾動的。對于窗口高度來說,也存在innerWidth。使用pageYOffset(當前滾動位置)除以最大滾動位置,并乘以 100,就可以得到進度條長度。
調用滾動事件的preventDefault無法阻止滾動。實際上,事件處理器是在進行滾動之后才觸發的。
焦點事件當元素獲得焦點時,瀏覽器會觸發其上的focus事件。當失去焦點時,元素會獲得blur事件。
與前文討論的事件不同,這兩個事件不會傳播。子元素獲得或失去焦點時,不會激活父元素的處理器。
下面的示例中,文本域在擁有焦點時會顯示幫助文本。
Name:
Age:
當用戶從瀏覽器標簽或窗口移開時,窗口對象會收到focus事件,當移動到標簽或窗口上時,則收到blur事件。
加載事件當界面結束裝載時,會觸發窗口對象和文檔body對象的"load"事件。該事件通常用于在當整個文檔構建完成時,進行初始化。請記住
將undefined傳遞給clearTimeout或在一個已結束的定時器上調用clearTimeout是沒有效果的。因此,我們不需要關心何時調用該方法,只需要每個事件中都這樣做即可。
如果我們想要保證每次響應之間至少間隔一段時間,但不希望每次事件發生時都重置定時器,而是在一連串事件連續發生時能夠定時觸發響應,那么我們可以使用一個略有區別的方法來解決問題。例如,我們想要響應"mousemove"事件來顯示當前鼠標坐標,但頻率只有 250ms。
本章小結事件處理器可以檢測并響應發生在我們的 Web 頁面上的事件。addEventListener方法用于注冊處理器。
每個事件都有標識事件的類型(keydown、focus等)。大多數方法都會在特定 DOM 元素上調用,接著向其父節點傳播,允許每個父元素的處理器都能處理這些事件。
JavaScript 調用事件處理器時,會傳遞一個包含事件額外信息的事件對象。該對象也有方法支持停止進一步傳播(stopPropagation),也支持阻止瀏覽器執行事件的默認處理器(preventDefault)。
按下鍵盤按鍵時會觸發keydown和keyup事件。按下鼠標按鈕時,會觸發mousedown、mouseup和click事件。移動鼠標會觸發mousemove事件。觸摸屏交互會導致"touchstart","touchmove"和"touchend"事件。
我們可以通過scroll事件監測滾動行為,可以通過focus和blur事件監控焦點改變。當文檔完成加載后,會觸發窗口的load事件。
習題 氣球編寫一個顯示氣球的頁面(使用氣球 emoji,ud83cudf88)。 當你按下上箭頭時,它應該變大(膨脹)10%,而當你按下下箭頭時,它應該縮小(放氣)10%。
您可以通過在其父元素上設置font-size CSS 屬性(style.fontSize)來控制文本大小(emoji 是文本)。 請記住在該值中包含一個單位,例如像素(10px)。
箭頭鍵的鍵名是"ArrowUp"和"ArrowDown"。確保按鍵只更改氣球,而不滾動頁面。
實現了之后,添加一個功能,如果你將氣球吹過一定的尺寸,它就會爆炸。 在這種情況下,爆炸意味著將其替換為“爆炸 emoji,ud83dudca5”,并且移除事件處理器(以便您不能使爆炸變大變小)。
鼠標軌跡💥
在 JavaScript 早期,有許多主頁都會在頁面上使用大量的動畫,人們想出了許多該語言的創造性用法。
其中一種是“鼠標蹤跡”,也就是一系列的元素,隨著你在頁面上移動鼠標,它會跟著你的鼠標指針。
在本習題中實現鼠標軌跡的功能。使用絕對定位、固定尺寸的 有許多方案可以實現我們所需的功能。你可以根據你的需要實現簡單的或復雜的方法。簡單的解決方案是保存固定鼠標的軌跡元素并循環使用它們,每次mousemove事件觸發時將下一個元素移動到鼠標當前位置。 選項卡面板廣泛用于用戶界面。它支持用戶通過選擇元素上方的很多突出的選項卡來選擇一個面板。 本習題中,你必須實現一個簡單的選項卡界面。編寫asTabs函數,接受一個 DOM 節點并創建選項卡界面來展現該節點的子元素。該函數應該在頂層節點中插入大量元素,與每個子元素一一對應,按鈕文本從子節點的data-tabname中獲取。除了顯示一個初始子節點,其他子節點都應該隱藏(將display樣式設置成none),并通過點擊按鈕來選擇當前顯示的節點。 當它生效時將其擴展,為當前選中的選項卡,將按鈕的樣式設為不同的,以便明確選擇了哪個選項卡。 文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。 轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/105048.html
選項卡
摘要:相反,當響應指針事件時,它會調用創建它的代碼提供的回調函數,該函數將處理應用的特定部分。回調函數可能會返回另一個回調函數,以便在按下按鈕并且將指針移動到另一個像素時得到通知。它們為組件構造器的數組而提供。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項目原文:Project: A Pixel Art Editor 譯者:飛龍 協議:CC BY-NC-SA 4...
摘要:來源編程精解中文第三版翻譯項目原文譯者飛龍協議自豪地采用谷歌翻譯部分參考了編程精解第版,這是一本關于指導電腦的書。在可控的范圍內編寫程序是編程過程中首要解決的問題。我們可以用中文來描述這些指令將數字存儲在內存地址中的位置。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項目原文:Introduction 譯者:飛龍 協議:CC BY-NC-SA 4.0 自豪地...
摘要:為了運行包裹的程序,可以將這些值應用于它們。在瀏覽器中,輸出出現在控制臺中。在英文版頁面上運行示例或自己的代碼時,會在示例之后顯示輸出,而不是在瀏覽器的控制臺中顯示。這被稱為條件執行。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項目原文:Program Structure 譯者:飛龍 協議:CC BY-NC-SA 4.0 自豪地采用谷歌翻譯 部分參考了《J...
摘要:在本例中,使用屬性指定鏈接的目標,其中表示超文本鏈接。您應該認為和元數據隱式出現在示例中,即使它們沒有實際顯示在文本中。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項目原文:JavaScript and the Browser 譯者:飛龍 協議:CC BY-NC-SA 4.0 自豪地采用谷歌翻譯 部分參考了《JavaScript 編程精解(第 2 版)》 ...
摘要:來源編程精解中文第三版翻譯項目原文譯者飛龍協議自豪地采用谷歌翻譯部分參考了編程精解第版在機器的表面之下,程序在運轉。本章將會介紹程序當中的基本元素,包括簡單的值類型以及值運算符。示例中的乘法運算符優先級高于加法。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項目原文:Values, Types, and Operators 譯者:飛龍 協議:CC BY-NC...
閱讀 2188·2021-11-15 11:38
閱讀 1151·2021-09-06 15:02
閱讀 3380·2021-08-27 13:12
閱讀 1353·2019-08-30 14:20
閱讀 2389·2019-08-29 15:08
閱讀 636·2019-08-29 14:08
閱讀 1723·2019-08-29 13:43
閱讀 1464·2019-08-26 12:11