日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

詳解JS瀏覽器事件模型

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

我想你很可能聽說過事件驅(qū)動(dòng), 但是事件驅(qū)動(dòng)到底是什么?為什么說瀏覽器是事件驅(qū)動(dòng)的呢?

事件驅(qū)動(dòng)通俗地來說就是什么都抽象為事件。

一次點(diǎn)擊是一個(gè)事件 鍵盤按下是一個(gè)事件 一個(gè)網(wǎng)絡(luò)請(qǐng)求成功是一個(gè)事件 頁(yè)面加載是一個(gè)事件 頁(yè)面報(bào)錯(cuò)是一個(gè)事件

瀏覽器依靠事件來驅(qū)動(dòng)APP運(yùn)行下去,如果沒有了事件驅(qū)動(dòng),那么APP會(huì)直接從頭到尾運(yùn)行完,然后結(jié)束,事件驅(qū)動(dòng)是瀏覽器的基石。

一個(gè)簡(jiǎn)單的例子

其實(shí)現(xiàn)實(shí)中的紅綠燈就是一種事件,它告訴我們現(xiàn)在是紅燈狀態(tài),綠燈狀態(tài),還是黃燈狀態(tài)。 我們需要根據(jù)這個(gè)事件自己去完成一些操作,比如紅燈和黃燈我們需要等待,綠燈我們可以過馬路。

下面我們來看一個(gè)最簡(jiǎn)單的瀏覽器端的事件:

html代碼:

<button>Change color</button>

js代碼:

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

代碼很簡(jiǎn)單,我們?cè)赽utton上注冊(cè)了一個(gè)事件,這個(gè)事件的handler是一個(gè)我們定義的匿名函數(shù)。當(dāng)用戶點(diǎn)擊了這個(gè)被注冊(cè)了事件的button的時(shí)候,這個(gè)我們定義好的匿名函數(shù)就會(huì)被執(zhí)行。

如何綁定事件

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

內(nèi)聯(lián)這個(gè)方法非常不推薦

html代碼:

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

然后在script標(biāo)簽內(nèi)寫:

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

直接賦值

和我上面舉的例子一樣:

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

這種方法有兩個(gè)缺點(diǎn)

不能添加多個(gè)同類型的handler

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

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

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

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

addEventListener

舊版本的addEventListener第三個(gè)參數(shù)是bool,新版版的第三個(gè)參數(shù)是對(duì)象,這樣方便之后的擴(kuò)展,承載更多的功能, 我們來重點(diǎn)介紹一下它。

addEventListener可以給Element,Document,Window,甚至XMLHttpRequest等綁定事件,當(dāng)指定的事件發(fā)生的時(shí)候,綁定的回調(diào)函數(shù)就會(huì)被以某種機(jī)制進(jìn)行執(zhí)行,這種機(jī)制我們稍后就會(huì)講到。

語法:

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

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

框架中的事件

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

React SyntheticEvent Vue和React的優(yōu)點(diǎn)分別是什么??jī)烧叩淖詈诵牟町悓?duì)比是什么?

雖然我們很少時(shí)候會(huì)接觸到原生的事件,但是了解一下事件對(duì)象,事件機(jī)制,事件代理等還是很有必要的,因?yàn)榭蚣艿氖录到y(tǒng)至少在這方面還是一致的,這些內(nèi)容我們接下來就會(huì)講到。

事件對(duì)象

所有的事件處理函數(shù)在被瀏覽器執(zhí)行的時(shí)候都會(huì)帶上一個(gè)事件對(duì)象,舉個(gè)例子:

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

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

屬性

target x, y等位置信息 timeStamp eventPhase

方法

preventDefault 用于阻止瀏覽器的默認(rèn)行為,比如a標(biāo)簽會(huì)默認(rèn)進(jìn)行跳轉(zhuǎn),form會(huì)默認(rèn)校驗(yàn)并發(fā)送請(qǐng)求到action指定的地址等 stopPropagation 用于阻止事件的繼續(xù)冒泡行為,后面講事件傳播的時(shí)候會(huì)提到。事件傳播

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

事件捕獲很有意思,以至于我會(huì)經(jīng)常出事件的題目加上一點(diǎn)事件傳播的機(jī)制,讓候選人進(jìn)行回答,這很能體現(xiàn)一個(gè)人的水平。了解事件的傳播機(jī)制,對(duì)于一些特定問題有著非常大的作用。

一個(gè)Element上綁定的事件觸發(fā)了,那么其實(shí)會(huì)經(jīng)過三個(gè)階段。

第一個(gè)階段 - 捕獲階段

從最外層即HTML標(biāo)簽開始,檢查當(dāng)前元素有沒有綁定對(duì)應(yīng)捕獲階段事件,如果有則執(zhí)行,沒有則繼續(xù)往里面?zhèn)鞑ィ@個(gè)過程遞歸執(zhí)行直到觸達(dá)觸發(fā)這個(gè)事件的元素為止。

偽代碼:

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用于獲取當(dāng)前事件傳播鏈路上的子節(jié)點(diǎn)capture(e, getActiveChild(currentElement, e)) } else {bubble(e, currentElement) }}// 這個(gè)Event對(duì)象由引擎創(chuàng)建capture(new Event(), document.querySelector(’html’))

第二個(gè)階段 - 目標(biāo)階段

上面已經(jīng)提到了,這里省略了。

第三個(gè)階段 - 冒泡階段

從觸發(fā)這個(gè)事件的元素開始,檢查當(dāng)前元素有沒有綁定對(duì)應(yīng)冒泡階段事件,如果有則執(zhí)行,沒有則繼續(xù)往里面?zhèn)鞑ィ@個(gè)過程遞歸執(zhí)行直到觸達(dá)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瀏覽器事件模型

如果你不希望事件繼續(xù)冒泡,可以用之前我提到的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) }}事件代理

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

我們有一個(gè)如下的列表,我們想在點(diǎn)擊對(duì)應(yīng)列表項(xiàng)的時(shí)候,輸出是點(diǎn)擊了哪個(gè)元素。

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會(huì)默認(rèn)綁定到冒泡階段,因此事件會(huì)從目標(biāo)階段開始,向外層冒泡,到我們綁定了事件的ul上,ul中通過事件對(duì)象的target屬性就能獲取到是哪一個(gè)元素觸發(fā)的。

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

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

這個(gè)有趣的東西,我們給了它一個(gè)好聽的名字“事件代理”。在實(shí)際業(yè)務(wù)中我們會(huì)經(jīng)常使用到這個(gè)技巧,這同時(shí)也是面試的高頻考點(diǎn)。

總結(jié)

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

我們今天講的是瀏覽器的事件模型,瀏覽器基于事件驅(qū)動(dòng),將很多東西都抽象為事件,比如用戶交互,網(wǎng)絡(luò)請(qǐng)求,頁(yè)面加載,報(bào)錯(cuò)等,可以說事件是瀏覽器正常運(yùn)行的基石。

我們?cè)谑褂玫目蚣芏紝?duì)事件進(jìn)行了不同程度的封裝和處理,除了了解原生的事件和原理,有時(shí)候了解一下框架本身對(duì)事件的處理也是很有必要的。

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

事件對(duì)象有很多屬性和方法,允許你在事件處理函數(shù)中進(jìn)行讀取和操作,比如讀取點(diǎn)擊的坐標(biāo)信息,阻止冒泡等。

最后我們通過一個(gè)例子,說明了如何利用冒泡機(jī)制來實(shí)現(xiàn)事件代理。

以上就是詳解JS瀏覽器事件模型的詳細(xì)內(nèi)容,更多關(guān)于JS瀏覽器事件模型的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: JavaScript
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
久久精品影视| 日韩av在线播放中文字幕| 日韩综合一区二区| 欧美/亚洲一区| 国产成人1区| 中文字幕一区二区精品区| 在线人成日本视频| 老司机精品视频在线播放| 亚洲一区二区动漫| 亚洲成人一区| 麻豆精品蜜桃| av高清不卡| 国产黄色一区| 国产精品伊人| 久久国内精品自在自线400部| 首页欧美精品中文字幕| 天堂资源在线亚洲| 久久国产免费| 99热精品久久| 日韩在线中文| 91精品一区二区三区综合| 国产一区二区亚洲| 国产一区二区三区四区大秀 | 在线免费观看亚洲| 欧美女激情福利| 影音先锋国产精品| 99久精品视频在线观看视频| 91精品xxx在线观看| 夜鲁夜鲁夜鲁视频在线播放| 伊人久久在线| 日韩视频网站在线观看| 成人久久久久| 伊人久久成人| 在线天堂资源www在线污| 精品国产亚洲日本| 欧美日韩在线网站| 日韩av一区二区在线影视| 精品少妇一区| 亚洲高清影视| 国产欧美精品| 久久亚洲成人| 日韩激情综合| 性欧美videohd高精| 免费成人在线视频观看| 国产精品免费99久久久| 久久精品国产www456c0m| 亚洲欧美在线综合| 国产中文在线播放| 亚洲三级国产| 成人亚洲精品| 欧美中文字幕| 精品国产欧美日韩一区二区三区| 亚洲精品2区| 国产精品亚洲综合色区韩国| 久久影院一区| 欧美午夜三级| 欧美特黄一级| 精品一区二区三区亚洲 | 欧美精品国产| 国产精品7m凸凹视频分类| 欧美日一区二区三区在线观看国产免| 日韩综合精品| 天堂成人免费av电影一区 | 91久久午夜| 久久97视频| 亚洲精选91| 久久天堂精品| 精品一区视频| 日韩欧美2区| 激情久久五月| 久久精品国产99国产| 丝袜脚交一区二区| 欧美三区四区| 麻豆久久一区| 亚洲图片久久| 成人羞羞在线观看网站| 国产精品一区二区中文字幕| 亚洲激情二区| 国产99在线| 国产欧美一区二区三区米奇| 91精品成人| 欧美激情另类| 国产精品一页| 伊人久久亚洲| 午夜日韩福利| 欧美aa在线观看| 久久免费影院| 国产精品一卡| 亚洲欧洲美洲国产香蕉| 久久精品免费一区二区三区 | 日韩1区2区日韩1区2区| 妖精视频成人观看www| 亚洲国产成人二区| 国产精品入口久久| 婷婷视频一区二区三区| 午夜电影亚洲| 视频福利一区| 人在线成免费视频| 麻豆精品av| 国产九一精品| 日韩视频1区| 一区二区精彩视频| 六月婷婷一区| 欧美肉体xxxx裸体137大胆| 日韩不卡一区| 久久久免费人体| 国产视频一区二| 日韩精品视频一区二区三区| 日本欧美在线看| 亚洲欧洲一区二区天堂久久| 蜜桃国内精品久久久久软件9| 韩国久久久久久| 国产理论在线| 亚洲三级欧美| 成人羞羞视频播放网站| 福利在线一区| 国产精品成久久久久| 国产91在线播放精品| 精品一区二区三区的国产在线观看| 欧美日韩黄网站| 国产精品一区二区精品视频观看 | 成人看片网站| 色婷婷精品视频| 激情久久婷婷| 夜夜嗨av一区二区三区网站四季av| 激情五月综合网| 国内精品福利| 亚洲欧美久久久| 亚洲午夜国产成人| 日韩不卡一区二区三区| 欧美日本精品| 欧美精品aa| 国产精品伦理久久久久久| 国产传媒在线观看| 999国产精品| 国产美女一区| 日本国产一区| 国产精品66| 伊人久久视频| 亚洲男女av一区二区| 免费日韩av| 亚洲欧洲日韩精品在线| 91亚洲精品在看在线观看高清| 国产欧美日韩免费观看| 免费看久久久| 日韩大片在线播放| 欧美在线亚洲综合一区| 免费人成在线不卡| 国产伦理久久久久久妇女| 国产 日韩 欧美 综合 一区| 久久精品动漫| 一级欧美视频| 国产精品久久久久久久久久妞妞| 国产一区丝袜| 激情久久五月| 亚洲欧洲国产精品一区| 久久精品97| 日本午夜大片a在线观看| 99国产精品自拍| 欧美综合社区国产| 国产一二在线播放| 国产一级久久| 国产剧情在线观看一区| 波多视频一区| 中文无码久久精品| 麻豆久久久久久| 91久久国产| 国产日韩欧美一区二区三区 | 亚洲精品伊人| 麻豆91在线播放| 国产综合精品| 国产欧美久久一区二区三区| 久久精品亚洲欧美日韩精品中文字幕| 三级欧美韩日大片在线看| 国产麻豆精品久久| 蜜桃视频欧美| 国产精品天天看天天狠| 免费观看久久av| 国产精品视频首页| 99riav国产精品| 麻豆精品视频在线观看| 99国产精品| 久久精品亚洲一区二区| 99视频精品免费观看| 欧美亚洲一级| 国产韩日影视精品| 国产精品久久777777毛茸茸| 欧美日韩国产在线观看网站| 国产精品亚洲人成在99www| 亚洲午夜黄色| 国产精品蜜月aⅴ在线| 欧美69视频| 精品视频在线一区二区在线| 日韩中文字幕不卡| 亚洲1234区| 国产精品亚洲四区在线观看| 黄页网站一区| 激情视频网站在线播放色| 亚洲ww精品| 韩国精品主播一区二区在线观看|