讀v-click-outside源碼

v-click-outside介紹

v-click-outside github地址

使用在Vue中的插件盒齿,一個(gè)附加的指令插件,作用是:

  1. 點(diǎn)擊指定元素外的區(qū)域可以觸發(fā)事件
  2. 可以綁定多個(gè)元素,一個(gè)元素上可以綁定多個(gè)事件
  3. 有中間件的概念,其實(shí)也就是個(gè)攔截器

核心實(shí)現(xiàn)代碼

function onEvent({ el, event, handler, middleware }) {
  // 判斷點(diǎn)擊事件觸發(fā)的元素(event.target)是否是綁定元素(el)的子元素
  const isClickOutside = event.target !== el && !el.contains(event.target)
  // 如果不是外部則不觸發(fā)
  if (!isClickOutside) {
    return
  }
  // middleware是中間件(攔截器),根據(jù)返回值可以決定是否攔截肖粮,同時(shí)還會(huì)執(zhí)行middleware內(nèi)部的代碼
  if (middleware(event, el)) {
    // 綁定的點(diǎn)擊元素外區(qū)域的觸發(fā)函數(shù)
    handler(event, el)
  }
}

創(chuàng)建觸發(fā)事件的實(shí)例

對(duì)其中的參數(shù)和格式做處理,為簡化后續(xù)創(chuàng)建尔苦,處理后是一個(gè)對(duì)象涩馆,里面包含el當(dāng)前綁定元素和eventHandlers綁定事件的數(shù)組列表

eventHandlers中每個(gè)對(duì)象又包含event事件名和handler事件處理函數(shù)

  • el:綁定事件的元素
  • events:數(shù)組,可以綁定多個(gè)事件允坚,比如:blur,foucs等魂那,默認(rèn)是click(PC),移動(dòng)端是click和tap
  • handler:綁定的事件觸發(fā)的函數(shù)
  • middleware:中間件
function createInstance({ el, events, handler, middleware }) {
  return {
    el,
    eventHandlers: events.map((eventName) => ({
      event: eventName,
      handler: (event) => onEvent({ event, el, handler, middleware }),
    })),
  }
}

初始化實(shí)例并綁定

這里面有2個(gè)小細(xì)節(jié):

  1. 采用定時(shí)器注冊(cè)事件稠项,實(shí)現(xiàn)類似異步注冊(cè)涯雅,提高效率
  2. 將創(chuàng)建好的實(shí)例存放在數(shù)組緩存為后續(xù)注銷和修改使用
function bind(el, { value }) {
  // 處理參數(shù)和初始值問題
  const { events, handler, middleware, isActive } = processDirectiveArguments(value)
  // 是否可用的開關(guān)
  if (!isActive) {
    return
  }
  // 初始化實(shí)例
  const instance = createInstance({ el, events, handler, middleware })
  // 根據(jù)初始化后的實(shí)例,去循環(huán)綁定指定的事件和事件處理函數(shù)
  instance.eventHandlers.forEach(({ event, handler }) =>
    setTimeout(() => document.addEventListener(event, handler), 0),
  )
  // 存放在數(shù)組緩存中
  directive.instances.push(instance)
}

注銷已初始化的實(shí)例

有兩點(diǎn)注意:

  1. 注銷事件時(shí)展运,不能用setTimeout活逆,因?yàn)樾枰饺孔N完后做清除緩存實(shí)例的動(dòng)作
  2. removeEventListener中的處理函數(shù)必須用addEventListener中的處理函數(shù),所以這里緩存就起到作用了拗胜,如果只是單純的函數(shù)一樣是沒辦法注銷的
function removeInstance(el) {
  // 讀取緩存中el的實(shí)例
  const instanceIndex = directive.instances.findIndex((instance) => instance.el === el)
  // 如果不存在實(shí)例則停止注銷
  if (instanceIndex === -1) {
    // Note: This can happen when active status changes from false to false
    return
  }
  // 緩存中el的實(shí)例
  const instance = directive.instances[instanceIndex]
  // 循環(huán)注銷
  instance.eventHandlers.forEach(({ event, handler }) =>
    document.removeEventListener(event, handler),
  )
  // 清除緩存中的注銷實(shí)例
  directive.instances.splice(instanceIndex, 1)
}

解讀源碼的原因

由于v-click-outside只能在Vue中以指令的蔗候,但是有時(shí)候可能用不了指令,比如動(dòng)態(tài)生成的元素埂软,也有可能不是在Vue中想要用到锈遥,所以通過讀源碼開發(fā)一個(gè)原生js庫

最后發(fā)布了:

outside-click-js npm庫

outside-click-js github地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子所灸,更是在濱河造成了極大的恐慌儿礼,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件庆寺,死亡現(xiàn)場離奇詭異,居然都是意外死亡诉字,警方通過查閱死者的電腦和手機(jī)懦尝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來壤圃,“玉大人陵霉,你說我怎么就攤上這事∥樯” “怎么了踊挠?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長冲杀。 經(jīng)常有香客問我效床,道長,這世上最難降的妖魔是什么权谁? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任剩檀,我火速辦了婚禮,結(jié)果婚禮上旺芽,老公的妹妹穿的比我還像新娘沪猴。我一直安慰自己,他們只是感情好采章,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布运嗜。 她就那樣靜靜地躺著,像睡著了一般悯舟。 火紅的嫁衣襯著肌膚如雪担租。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天图谷,我揣著相機(jī)與錄音翩活,去河邊找鬼。 笑死便贵,一個(gè)胖子當(dāng)著我的面吹牛菠镇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播承璃,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼利耍,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起隘梨,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤程癌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后轴猎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嵌莉,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年捻脖,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了锐峭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡可婶,死狀恐怖沿癞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情矛渴,我是刑警寧澤椎扬,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站具温,受9級(jí)特大地震影響蚕涤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜铣猩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一钻趋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧剂习,春花似錦蛮位、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至们何,卻和暖如春萄焦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背冤竹。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國打工拂封, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鹦蠕。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓冒签,卻偏偏與公主長得像,于是被迫代替她去往敵國和親钟病。 傳聞我的和親對(duì)象是個(gè)殘疾皇子萧恕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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

  • vue概述 在官方文檔中刚梭,有一句話對(duì)Vue的定位說的很明確:Vue.js 的核心是一個(gè)允許采用簡潔的模板語法來聲明...
    li4065閱讀 7,191評(píng)論 0 25
  • ??JavaScript 與 HTML 之間的交互是通過事件實(shí)現(xiàn)的朴读。 ??事件,就是文檔或?yàn)g覽器窗口中發(fā)生的一些特...
    霜天曉閱讀 3,473評(píng)論 1 11
  • 主要還是自己看的走趋,所有內(nèi)容來自官方文檔衅金。 介紹 Vue.js 是什么 Vue (讀音 /vju?/,類似于 vie...
    Leonzai閱讀 3,329評(píng)論 0 25
  • 第一章 Vue概述 what? Vue是實(shí)現(xiàn)UI層的漸進(jìn)式j(luò)s框架簿煌,核心庫關(guān)注視圖層典挑,簡單的ui構(gòu)建,復(fù)雜的路由控...
    fastwe閱讀 701評(píng)論 0 0
  • 第3章 基本概念 3.1 語法 3.2 關(guān)鍵字和保留字 3.3 變量 3.4 數(shù)據(jù)類型 5種簡單數(shù)據(jù)類型:Unde...
    RickCole閱讀 5,099評(píng)論 0 21