成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術文章
文章詳情頁

詳解JS瀏覽器事件模型

瀏覽:175日期:2024-03-27 10:16:13
什么是事件

我想你很可能聽說過事件驅動, 但是事件驅動到底是什么?為什么說瀏覽器是事件驅動的呢?

事件驅動通俗地來說就是什么都抽象為事件。

一次點擊是一個事件 鍵盤按下是一個事件 一個網絡請求成功是一個事件 頁面加載是一個事件 頁面報錯是一個事件

瀏覽器依靠事件來驅動APP運行下去,如果沒有了事件驅動,那么APP會直接從頭到尾運行完,然后結束,事件驅動是瀏覽器的基石。

一個簡單的例子

其實現實中的紅綠燈就是一種事件,它告訴我們現在是紅燈狀態,綠燈狀態,還是黃燈狀態。 我們需要根據這個事件自己去完成一些操作,比如紅燈和黃燈我們需要等待,綠燈我們可以過馬路。

下面我們來看一個最簡單的瀏覽器端的事件:

html代碼:

<button>Change color</button>

js代碼:

var btn = document.querySelector(’button’);btn.onclick = function() { console.log(’button clicked’)}

代碼很簡單,我們在button上注冊了一個事件,這個事件的handler是一個我們定義的匿名函數。當用戶點擊了這個被注冊了事件的button的時候,這個我們定義好的匿名函數就會被執行。

如何綁定事件

我們有三種方法可以綁定事件,分別是行內綁定,直接賦值,用addEventListener。

內聯這個方法非常不推薦

html代碼:

<button onclick='handleClick()'>Press me</button>

然后在script標簽內寫:

function handleClick() { console.log(’button clicked’)}

直接賦值

和我上面舉的例子一樣:

var btn = document.querySelector(’button’);btn.onclick = function() { console.log(’button clicked’)}

這種方法有兩個缺點

不能添加多個同類型的handler

btn.onclick = functionA;btn.onclick = functionB;

這樣只有functionB有效,這可以通過addEventListener來解決。

不能控制在哪個階段來執行,這個會在后面將事件捕獲/冒泡的時候講到。這個同樣可以通過addEventListener來解決。

因此addEventListener橫空出世,這個也是目前推薦的寫法。

addEventListener

舊版本的addEventListener第三個參數是bool,新版版的第三個參數是對象,這樣方便之后的擴展,承載更多的功能, 我們來重點介紹一下它。

addEventListener可以給Element,Document,Window,甚至XMLHttpRequest等綁定事件,當指定的事件發生的時候,綁定的回調函數就會被以某種機制進行執行,這種機制我們稍后就會講到。

語法:

target.addEventListener(type, listener[, options]);target.addEventListener(type, listener[, useCapture]);target.addEventListener(type, listener[, useCapture, wantsUntrusted ]); // Gecko/Mozilla only

type是你想要綁定的事件類型,常見的有click, scroll, touch, mouseover等,舊版本的第三個參數是bool,表示是否是捕獲階段,默認是false,即默認為冒泡階段。新版本是一個對象,其中有capture(和上面功能一樣),passive和once。 once用來執行是否只執行一次,passive如果被指定為true表示永遠不會執行preventDefault(),這在實現絲滑柔順的滾動的效果中很重要。更多請參考Improving scrolling performance with passive listeners

框架中的事件

實際上,我們現在大多數情況都是用框架來寫代碼,因此上面的情況其實在現實中是非常少見的,我們更多看到的是框架封裝好的事件,比如react的合成事件,感興趣的可以看下這幾篇文章。

React SyntheticEvent Vue和React的優點分別是什么?兩者的最核心差異對比是什么?

雖然我們很少時候會接觸到原生的事件,但是了解一下事件對象,事件機制,事件代理等還是很有必要的,因為框架的事件系統至少在這方面還是一致的,這些內容我們接下來就會講到。

事件對象

所有的事件處理函數在被瀏覽器執行的時候都會帶上一個事件對象,舉個例子:

function handleClick(e) { console.log(e);} btn.addEventListener(’click’, handleClick);

這個e就是事件對象,即event object。 這個對象有一些很有用的屬性和方法,下面舉幾個常用的屬性和方法。

屬性

target x, y等位置信息 timeStamp eventPhase

方法

preventDefault 用于阻止瀏覽器的默認行為,比如a標簽會默認進行跳轉,form會默認校驗并發送請求到action指定的地址等 stopPropagation 用于阻止事件的繼續冒泡行為,后面講事件傳播的時候會提到。事件傳播

前面講到了事件默認是綁定到冒泡階段的,如果你顯式令useCapture為true,則會綁定到捕獲階段。

事件捕獲很有意思,以至于我會經常出事件的題目加上一點事件傳播的機制,讓候選人進行回答,這很能體現一個人的水平。了解事件的傳播機制,對于一些特定問題有著非常大的作用。

一個Element上綁定的事件觸發了,那么其實會經過三個階段。

第一個階段 - 捕獲階段

從最外層即HTML標簽開始,檢查當前元素有沒有綁定對應捕獲階段事件,如果有則執行,沒有則繼續往里面傳播,這個過程遞歸執行直到觸達觸發這個事件的元素為止。

偽代碼:

function capture(e, currentElement) { if (currentElement.listners[e.type] !== void 0) {currentElement.listners[e.type].forEach(fn => fn(e)) } // pass down if (currentElement !== e.target) {// getActiveChild用于獲取當前事件傳播鏈路上的子節點capture(e, getActiveChild(currentElement, e)) } else {bubble(e, currentElement) }}// 這個Event對象由引擎創建capture(new Event(), document.querySelector(’html’))

第二個階段 - 目標階段

上面已經提到了,這里省略了。

第三個階段 - 冒泡階段

從觸發這個事件的元素開始,檢查當前元素有沒有綁定對應冒泡階段事件,如果有則執行,沒有則繼續往里面傳播,這個過程遞歸執行直到觸達HTML為止。

偽代碼:

function bubble(e, currentElement) { if (currentElement.listners[e.type] !== void 0) {currentElement.listners[e.type].forEach(fn => fn(e)) } // returning if (currentElement !== document.querySelector(’html’)) {bubble(e, currentElement.parent) }}

上述的過程用圖來表示為:

詳解JS瀏覽器事件模型

如果你不希望事件繼續冒泡,可以用之前我提到的stopPropagation。

偽代碼:

function bubble(e, currentElement) { let stopped = false; function cb() {stopped = true; } if (currentElement.listners[e.type] !== void 0) {currentElement.listners[e.type].forEach(fn => { fn({...e,stopPropagation: cb }); if (stopped) return;}) } // returning if (currentElement !== document.querySelector(’html’)) {bubble(e, currentElement.parent) }}事件代理

利用上面提到的事件冒泡機制,我們可以選擇做一些有趣的東西。 舉個例子:

我們有一個如下的列表,我們想在點擊對應列表項的時候,輸出是點擊了哪個元素。

HTML代碼:

<ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li></ul>

JS代碼:

document.querySelector(’ul’).addEventListener(’click’, e => console.log(e.target.innerHTML))

在線地址,上面說了addEventListener會默認綁定到冒泡階段,因此事件會從目標階段開始,向外層冒泡,到我們綁定了事件的ul上,ul中通過事件對象的target屬性就能獲取到是哪一個元素觸發的。

“事件會從目標階段開始”,并不是說事件沒有捕獲階段,而是我們沒有綁定捕獲階段,我描述給省略了。

我們只給外層的ul綁定了事件處理函數,但是可以看到li點擊的時候,實際上會打印出對應li的內容(1,2,3或者4)。 我們無須給每一個li綁定事件處理函數,不僅從代碼量還是性能上都有一定程度的提升。

這個有趣的東西,我們給了它一個好聽的名字“事件代理”。在實際業務中我們會經常使用到這個技巧,這同時也是面試的高頻考點。

總結

事件其實不是瀏覽器特有的,和JS語言也沒有什么關系,這也是我為什么沒有將其劃分到JS部分的原因。很多地方都有事件系統,但是各種事件模型又不太一致。

我們今天講的是瀏覽器的事件模型,瀏覽器基于事件驅動,將很多東西都抽象為事件,比如用戶交互,網絡請求,頁面加載,報錯等,可以說事件是瀏覽器正常運行的基石。

我們在使用的框架都對事件進行了不同程度的封裝和處理,除了了解原生的事件和原理,有時候了解一下框架本身對事件的處理也是很有必要的。

當發生一個事件的時候,瀏覽器會初始化一個事件對象,然后將這個事件對象按照一定的邏輯進行傳播,這個邏輯就是事件傳播機制。 我們提到了事件傳播其實分為三個階段,按照時間先后順序分為捕獲階段,目標階段和冒泡階段。開發者可以選擇監聽不同的階段,從而達到自己想要的效果。

事件對象有很多屬性和方法,允許你在事件處理函數中進行讀取和操作,比如讀取點擊的坐標信息,阻止冒泡等。

最后我們通過一個例子,說明了如何利用冒泡機制來實現事件代理。

以上就是詳解JS瀏覽器事件模型的詳細內容,更多關于JS瀏覽器事件模型的資料請關注好吧啦網其它相關文章!

標簽: JavaScript
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
亚洲欧美激情视频在线观看一区二区三区| 亚洲日本在线天堂| 国产精品初高中害羞小美女文| 成人精品视频一区二区三区| 欧美精品99久久久**| 蜜臀av国产精品久久久久| 一本色道久久综合狠狠躁的推荐| 亚洲男人的天堂在线观看| 欧美激情视频一区二区三区在线播放| 日韩午夜av电影| 国产成人免费视频一区| 欧美日韩亚洲综合在线| 日韩高清不卡一区二区| 9色精品在线| 一区精品在线播放| 极品av少妇一区二区| 亚洲视频一区在线观看| 99riav国产精品| 亚洲激情第一区| 亚洲欧美日韩专区| 图片区小说区区亚洲影院| 久久黄色小说| 免费成人在线视频观看| 欧美综合视频在线观看| 国内成人精品2018免费看| 精品视频123区在线观看| 久久99精品久久久久| 精品视频一区 二区 三区| 国产在线精品不卡| 欧美一级高清大全免费观看| 国产精品亚洲午夜一区二区三区| 欧美一区二区三区免费在线看| 激情欧美日韩一区二区| 日韩欧美成人激情| 99国产精品久久久久久久久久| 欧美激情一区二区三区蜜桃视频 | 欧美精品一卡二卡| 国产一二精品视频| 日韩美女一区二区三区| 欧美在线影院| 国产精品九色蝌蚪自拍| 一本久久综合| 日韩高清不卡在线| 欧美美女喷水视频| 国产成人精品一区二区三区网站观看| 精品久久久久久最新网址| 91麻豆6部合集magnet| 综合久久一区二区三区| 国产日韩欧美三区| 蜜桃av一区二区在线观看| 日韩丝袜美女视频| 欧美成人蜜桃| 一区二区不卡在线播放 | 亚洲一区影音先锋| 91国偷自产一区二区三区成为亚洲经典| 久久精品国产一区二区三区免费看| 欧美色网站导航| jlzzjlzz亚洲日本少妇| 亚洲青青青在线视频| 老司机精品久久| 国产激情精品久久久第一区二区| 久久精品视频免费观看| 国产亚洲高清视频| 久久福利资源站| 2020国产精品| 亚洲精品系列| 日韩电影免费一区| 欧美变态tickling挠脚心| 欧美日韩一区二区三区四区在线观看 | 日韩一区二区电影| 欧美婷婷久久| 性做久久久久久久免费看| 91精品国产福利| 亚洲国产精品久久久久婷婷老年| 日本欧美久久久久免费播放网| 日韩一区二区三区视频在线观看| 国内精品**久久毛片app| 污片在线观看一区二区| 日韩三级伦理片妻子的秘密按摩| 亚洲小说欧美另类婷婷| 免费成人在线观看| 国产欧美一区二区三区在线老狼| 老司机一区二区三区| 成人免费观看男女羞羞视频| 亚洲精品国产视频| 欧美一区二区三区在线视频| 亚洲免费观看| 国产精品一区二区久久精品爱涩| 国产精品国产三级国产| 欧美三级乱人伦电影| 国产在线精品二区| 日韩国产欧美在线观看| xnxx国产精品| 蜜桃av综合| 99re亚洲国产精品| 水蜜桃久久夜色精品一区的特点 | 久久精品中文| 99精品久久久久久| 日本少妇一区二区| 国产精品天美传媒| 在线观看www91| 欧美国产一区二区三区激情无套| 日本视频免费一区| 国产精品免费视频一区| 欧美日韩中文另类| 最新成人av网站| 国产91精品一区二区| 亚洲电影一区二区三区| 2020国产精品久久精品美国| 色哟哟在线观看一区二区三区| 99精品视频一区二区| 性久久久久久久| 国产欧美日韩综合精品一区二区| 在线观看亚洲精品| 亚洲精品乱码久久久久久蜜桃91| 国产精品66部| 日本中文在线一区| 亚洲日本va在线观看| 精品免费视频.| 在线观看欧美黄色| 国产精品观看| 成人三级伦理片| 麻豆国产精品官网| 一区二区三区加勒比av| 久久久777精品电影网影网 | 在线成人av网站| 麻豆精品91| 亚洲午夜激情在线| 丰满亚洲少妇av| 美女mm1313爽爽久久久蜜臀| 亚洲乱码国产乱码精品精的特点 | 国产露脸91国语对白| 亚洲午夜电影网| 欧美国产一区在线| 精品美女一区二区| 欧美人与禽zozo性伦| 一本久久精品一区二区| 一区二区三区精品国产| 色综合咪咪久久| 成人在线视频首页| 麻豆国产91在线播放| 亚洲男女毛片无遮挡| 久久综合色婷婷| 88在线观看91蜜桃国自产| 色综合久久99| 亚洲欧美不卡| 亚洲激情欧美| 91免费国产在线| 国产mv日韩mv欧美| 国产在线播放一区二区三区| 奇米亚洲午夜久久精品| 亚洲成人激情综合网| 日韩毛片视频在线看| 久久久亚洲欧洲日产国码αv| 91精品国产欧美一区二区成人| 91国产福利在线| 美女尤物久久精品| 国产伦一区二区三区色一情| 在线免费观看欧美| 一色屋精品视频在线观看网站| 女女同性精品视频| 91网站在线观看视频| 成+人+亚洲+综合天堂| 国产精品99久久久久| 国产毛片精品国产一区二区三区| 免费看黄色91| 午夜欧美视频在线观看| 亚洲综合小说图片| 一区二区三区在线视频观看| 日韩一区欧美一区| 中文字幕亚洲电影| 中文字幕国产精品一区二区| 国产亚洲精品福利| 中文字幕成人网| 国产精品久久国产精麻豆99网站| 国产精品色眯眯| 国产精品久久久久aaaa樱花| 亚洲日韩欧美一区二区在线| 亚洲精品视频在线| 亚洲国产成人tv| 日韩精品一二区| 丝袜诱惑制服诱惑色一区在线观看 | 国产91丝袜在线播放九色| 国产福利精品导航| 成人深夜在线观看| 99r国产精品| 国产精品v欧美精品v日本精品动漫 | 国产农村妇女精品| 国产精品免费观看视频| 中文字幕在线一区免费| 亚洲免费毛片网站| 亚洲香肠在线观看| 免费高清在线视频一区·| 裸体在线国模精品偷拍| 狠狠色综合播放一区二区| 丰满白嫩尤物一区二区| 91女神在线视频| 亚洲国产一区二区三区在线播| 国产精品尤物| 日本韩国精品在线|