色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

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

JavaScript 事件代理需要注意的地方

瀏覽:66日期:2023-10-15 08:54:25

我們知道,如果給 form 里面的 button 元素綁定事件,需要考慮它是否會(huì)觸發(fā) form 的 submit 行為。除此之外,其它場(chǎng)合給 button 元素綁定事件,你幾乎不用擔(dān)心這個(gè)事件會(huì)有什么非預(yù)期的附加效果,很自然地會(huì)這樣寫事件處理代碼:

var button = document.querySelector(’button’)button.addEventListener(’click’, function (e) { console.log(’點(diǎn)擊了按鈕’)})

你之所以放心這么寫,是因?yàn)檫@個(gè) button 元素沒有使用事件代理,即沒有代理任何子元素的事件。

事件代理的意思是,你要為一個(gè)元素綁定事件,但你不是直接把事件綁定到這個(gè)元素自己身上,而是綁定到這個(gè)元素的父元素上。當(dāng)子元素的某個(gè)事件(比如點(diǎn)擊事件)觸發(fā)時(shí),它的父元素相同的事件也會(huì)觸發(fā)(我們常說的事件冒泡),此時(shí)我們說父元素代理了子元素的事件。

舉個(gè)例子,比如一個(gè) button 元素中包含一個(gè)齒輪圖標(biāo):

<button> <svg> <use xlink:href='http://www.lshqa.cn/bcjs/16526.html#gear' rel='external nofollow' ></use> </svg></button>

當(dāng)用戶點(diǎn)擊齒輪圖標(biāo),必然要觸發(fā) click 事件,但你并不會(huì)直接綁定事件到 svg 或 use 元素上,而是綁定到它們的父元素 button 上。即:

document.querySelector(’button’).addEventListener(’click’, function (e) { console.log(’點(diǎn)擊了按鈕’)})

這種情況,我們可以說,button 元素代理了它的所有子元素的 click 事件。

但是,出現(xiàn)這種事件代理的情況時(shí),我們就得小心了。

為了更直觀地說明問題,我們把“父”元素上升到頂層的 document 元素:

document.documentElement.addEventListener(’click’, function (e) { console.log(’我被點(diǎn)擊了’)})

只要網(wǎng)頁中任意一個(gè)位置被點(diǎn)擊了,都會(huì)觸發(fā)綁定在 document 元素上的點(diǎn)擊事件。​ 想要知道事件具體是發(fā)生在哪個(gè)元素上面,可以通過事件對(duì)象提供的 target 屬性來判斷。

document.documentElement.addEventListener(’click’, function (e) { console.log(e.target)})

我們很容易知道事件具體是發(fā)生在哪個(gè)元素身上的。于是在上面的示例中,如果父元素 document 想在按鈕被點(diǎn)擊時(shí)做點(diǎn)什么事情,我們很自然地會(huì)這么寫:

document.documentElement.addEventListener(’click’, function (e) { if (e.target.tagName === ’BUTTON’) { console.log(’按鈕被點(diǎn)擊了’) }})

這時(shí)問題就出現(xiàn)了,按鈕即使被點(diǎn)擊了 if 條件也不一定成立,即也不一定會(huì)輸出“按鈕被點(diǎn)擊了”。因?yàn)橛脩粼诎粹o上的某個(gè)位置點(diǎn)擊了,根據(jù)用戶點(diǎn)擊的位置,e.target 可能是下面三種情況:

BUTTON 元素 SVG 元素 USE 元素

實(shí)際的情況是這樣的:

JavaScript 事件代理需要注意的地方

我們真正的意圖是,只要點(diǎn)擊是發(fā)生在按鈕上面,不論是按鈕的哪個(gè)位置,我們都應(yīng)視為按鈕被點(diǎn)擊了。 嗯,簡(jiǎn)單,我們?cè)俑囊幌拢@樣寫:

document.documentElement.addEventListener(’click’, function (e) { if ([’BUTTON’, ’SVG’, ’USE’].includes(e.target.tagName.toUpperCase())) { // 點(diǎn)擊的是按鈕 }})

這樣似乎沒什么問題,也確實(shí)可以達(dá)到目的,但看上去總是有些別扭。因?yàn)檫@種情況對(duì)于最上層的 document 來說,得知道每個(gè)子元素的情況,本來我只需要關(guān)心離我最近的 button 元素就可以了。

根據(jù) OOP 對(duì)內(nèi)封裝的思想,button 元素內(nèi)部的事情應(yīng)該在內(nèi)部消化掉,其子元素對(duì)外不可見,應(yīng)該只暴露 button 元素本身。依據(jù)這個(gè)思想和事件冒泡的特點(diǎn),我們就有了比較好的解決辦法:只需要禁止 button 內(nèi)部元素的事件響應(yīng)(包括事件冒泡)而只允許 button 元素本身的事件發(fā)生就行。有兩種方式可以實(shí)現(xiàn)這個(gè)目的。

一種是使用 CSS 禁止 button 內(nèi)部元素的事件響應(yīng):

button > * { pointer-events: none;}

另一種是使用 JS 來阻止 button 內(nèi)部元素的事件響應(yīng)(包括事件冒泡):

document.querySelector(’button > svg’).addEventListener(’click’, function (e) { e.stopPropagation() e.preventDefault()})document.querySelector(’button’).addEventListener(’click’, function (e) { console.log(e.target.tagName)})

這兩種方式都能達(dá)到我們預(yù)期的效果:

JavaScript 事件代理需要注意的地方

綜上,針對(duì)特定元素進(jìn)行事件處理時(shí),如果該元素有事件代理的情況,就要小心處理它所代理的子元素。

以上就是JavaScript 事件代理需要注意的地方的詳細(xì)內(nèi)容,更多關(guān)于JavaScript 事件代理的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: JavaScript
相關(guān)文章:
主站蜘蛛池模板: 亚洲欧美国产一区二区三区 | 久草热草| 99久久99这里只有免费费精品 | 久草日韩 | 韩国19禁主播裸免费福利 | 久艹在线视频 | 欧美日韩另类国产 | 久久一区二区精品综合 | 国产精品免费_区二区三区观看 | 三级毛片在线播放 | 狠狠色综合网站久久久久久久 | 亚洲欧美日本在线 | 欧美一级毛片免费网站 | 久久99精品视免费看 | 国产精品免费看久久久久 | 国内外成人免费视频 | 国产精选经典三级小泽玛利亚 | 99久久免费国产精品 | 成人性色生活片全黄 | 精品国产亚一区二区三区 | 看一级毛片国产一级毛片 | 国产精品九九九久久九九 | 色综合久久88中文字幕 | 亚洲日本视频在线观看 | 我要看三级毛片 | 日本三级成人中文字幕乱码 | 日韩三级欧美 | 一区二区伦理 | 国产99久久精品 | 久久国产欧美 | 国产一区二区三区精品久久呦 | 全国男人的天堂网 | 一区二区三区精品国产 | 日韩欧美二区 | 一级片aaaa| 日本黄页网站在线观看 | 在线观看日韩 | 韩国一级黄色大片 | 国产亚洲人成a在线v网站 | 日韩美女视频网站 | 欧美日韩精品一区二区三区视频在线 |