使用原生 JS 實(shí)現(xiàn)事件委托

1 什么是事件委托?

用個(gè)例子就可以很簡(jiǎn)單的解釋事件委托是怎么一回事了:

假設(shè)一個(gè)公司有三個(gè)職員在網(wǎng)上買了東西,那么他們?nèi)齻€(gè)在接收快遞的時(shí)候有兩種方法并炮。
第一種:等快遞來的時(shí)候,自己下樓去拿郭怪。
第二種:快遞來的時(shí)候,先經(jīng)過公司前臺(tái),然后在分發(fā)給每個(gè)人卿闹。
然而,正常情況下,第一種顯然比較浪費(fèi)勞動(dòng)力,所以現(xiàn)實(shí)情況我們都采取第二種方法。
而且,第二種方法有個(gè)優(yōu)勢(shì),新加入的職員也可以享受代簽快遞的服務(wù)八毯。

我們把場(chǎng)景換到網(wǎng)頁(yè)上:

假設(shè)一個(gè)網(wǎng)頁(yè)中有三個(gè)li,并且綁定了事件,那么它們?nèi)齻€(gè)在觸發(fā)事件的時(shí)候有兩種方法袜炕。
第一種:當(dāng)用戶點(diǎn)擊了li的時(shí)候,li觸發(fā)事件
第二種:當(dāng)用戶點(diǎn)擊了ul的時(shí)候,ul中的li觸發(fā)事件
優(yōu)勢(shì),顯而易見就是新加入的li也可以通過ul觸發(fā)锭吨。

也就是說事件委托,就是把本該由li觸發(fā)的事件,交由ul代理。

2 為什么要用事件委托?

道理我都懂,可為什么要交給ul委托呢?我把每個(gè)li都綁定一遍不好嗎?

一般來說傲醉,dom需要有事件處理程序蝇闭,我們都會(huì)直接給它設(shè)事件處理程序就好了,那如果是很多的dom需要添加事件處理呢硬毕?比如我們有100個(gè)li呻引,每個(gè)li都有相同的click點(diǎn)擊事件,可能我們會(huì)用for循環(huán)的方法吐咳,來遍歷所有的li逻悠,然后給它們添加事件,那這么做會(huì)存在什么影響呢韭脊?

在JavaScript中童谒,添加到頁(yè)面上的事件處理程序數(shù)量將直接關(guān)系到頁(yè)面的整體運(yùn)行性能,因?yàn)樾枰粩嗟呐cdom節(jié)點(diǎn)進(jìn)行交互沪羔,訪問dom的次數(shù)越多饥伊,引起瀏覽器重繪與重排的次數(shù)也就越多,就會(huì)延長(zhǎng)整個(gè)頁(yè)面的交互就緒時(shí)間任内,這就是為什么性能優(yōu)化的主要思想之一就是減少DOM操作的原因撵渡;如果要用事件委托,就會(huì)將所有的操作放到j(luò)s程序里面死嗦,與dom的操作就只需要交互一次趋距,這樣就能大大的減少與dom的交互次數(shù),提高性能越除;

每個(gè)函數(shù)都是一個(gè)對(duì)象节腐,是對(duì)象就會(huì)占用內(nèi)存外盯,對(duì)象越多,內(nèi)存占用率就越大翼雀,自然性能就越差了(內(nèi)存不夠用饱苟,是硬傷,哈哈)狼渊,比如上面的100個(gè)li箱熬,就要占用100個(gè)內(nèi)存空間,如果是1000個(gè)狈邑,10000個(gè)呢城须,那只能說呵呵了,如果用事件委托米苹,那么我們就可以只對(duì)它的父級(jí)(如果只有一個(gè)父級(jí))這一個(gè)對(duì)象進(jìn)行操作糕伐,這樣我們就需要一個(gè)內(nèi)存空間就夠了,是不是省了很多蘸嘶,自然性能就會(huì)更好良瞧。

3 事件委托的原理

冒泡

事件委托是利用事件的冒泡原理來實(shí)現(xiàn)的,何為事件冒泡呢训唱?舉個(gè)例子:

  1. 先創(chuàng)建三個(gè)不同顏色的div,X>Y>Z


    我們先創(chuàng)建三個(gè)div
  2. 然后分別給XYZ綁定事件


    綁定事件
  3. 然后就可以測(cè)試冒泡事件了,我們先點(diǎn)擊一下最里面的黃色div,發(fā)現(xiàn)三個(gè)事件都觸發(fā)了


    三個(gè)事件都觸發(fā)了
  4. 我們?cè)冱c(diǎn)擊一下綠色div,發(fā)現(xiàn)只觸發(fā)了綠色div和紅色div的事件.


    只觸發(fā)了綠色div和紅色div的事件
  5. 所以我們可以總結(jié),事件冒泡的規(guī)則就是事件從最深的節(jié)點(diǎn)開始褥蚯,然后逐步向上傳播事件。同時(shí)這也是事件委托雪情,委托它們父級(jí)代為執(zhí)行事件遵岩。

4. 如何實(shí)現(xiàn)委托?

既然是委托,那么直接給li的父級(jí)ul綁定事件就可以了啊。但是這里存在一個(gè)BUG!
我們換個(gè)例子:
ul下有4個(gè)li,并且給ul綁定事件,為了方便演示給ul和li加一個(gè)border


BUG就是當(dāng)我們點(diǎn)擊紅色和綠色之間的時(shí)候也會(huì)觸發(fā)事件!!!

那么這個(gè)BUG如何處理呢?
如果在用戶點(diǎn)擊的時(shí)候判斷一下是不是點(diǎn)擊了li巡通,如果是就觸發(fā)尘执,如果不是就不觸發(fā),是不是就解決了?

加一步判斷

這樣看似成功了,只有點(diǎn)擊了li才會(huì)觸發(fā)事件.
但是并不完美,因?yàn)楫?dāng)li有子元素的時(shí)候就會(huì)失效!!!

這個(gè)時(shí)候點(diǎn)擊選項(xiàng)1的時(shí)候并不觸發(fā)事件

那么我們?cè)撊绾卫^續(xù)優(yōu)化呢?
當(dāng)我們發(fā)現(xiàn)被點(diǎn)擊的元素不是li的時(shí)候,那么我們就找被點(diǎn)擊元素的父元素,判斷它是不是li,如果不是就繼續(xù)找.......以此類推,當(dāng)我們找到li那么就觸發(fā)事件,如果沒找到,就不觸發(fā)宴凉。

觸發(fā)成功

最終代碼:

var ul = document.querySelector('.a')
ul.addEventListener('click', function (e) {
    var 被點(diǎn)擊的元素 = e.target
    while (被點(diǎn)擊的元素.tagName !== 'LI') {
        被點(diǎn)擊的元素 = 被點(diǎn)擊的元素.parentNode
        if (被點(diǎn)擊的元素 === ul) {
            被點(diǎn)擊的元素 = null
            break;
        }
    }
    if (被點(diǎn)擊的元素) {
        console.log('觸發(fā)成功')
    }
}) ```

















最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末誊锭,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子弥锄,更是在濱河造成了極大的恐慌丧靡,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件籽暇,死亡現(xiàn)場(chǎng)離奇詭異温治,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)戒悠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門熬荆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人绸狐,你說我怎么就攤上這事卤恳±鄣粒” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵突琳,是天一觀的道長(zhǎng)若债。 經(jīng)常有香客問我,道長(zhǎng)拆融,這世上最難降的妖魔是什么蠢琳? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮镜豹,結(jié)果婚禮上挪凑,老公的妹妹穿的比我還像新娘。我一直安慰自己逛艰,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布搞旭。 她就那樣靜靜地躺著散怖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪肄渗。 梳的紋絲不亂的頭發(fā)上镇眷,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音翎嫡,去河邊找鬼欠动。 笑死,一個(gè)胖子當(dāng)著我的面吹牛惑申,可吹牛的內(nèi)容都是我干的具伍。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼圈驼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼人芽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起绩脆,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤萤厅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后靴迫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惕味,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年玉锌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了名挥。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡芬沉,死狀恐怖躺同,靈堂內(nèi)的尸體忽然破棺而出阁猜,到底是詐尸還是另有隱情,我是刑警寧澤蹋艺,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布剃袍,位于F島的核電站,受9級(jí)特大地震影響捎谨,放射性物質(zhì)發(fā)生泄漏民效。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一涛救、第九天 我趴在偏房一處隱蔽的房頂上張望畏邢。 院中可真熱鬧,春花似錦检吆、人聲如沸舒萎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)臂寝。三九已至,卻和暖如春摊灭,著一層夾襖步出監(jiān)牢的瞬間咆贬,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工帚呼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留掏缎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓煤杀,卻偏偏與公主長(zhǎng)得像眷蜈,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子怜珍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容