成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

addEvent.js源碼解析

RaoMeng / 1136人閱讀

摘要:在看源碼時,發(fā)現(xiàn)了這段注釋源碼行的庫為的事件綁定提供了很多想法,我們就來看下年的。五內(nèi)存泄漏簡單說只綁定一次,只綁定一次。并通過來為每一個定一個,然后依次添加進(jìn)中,并通過執(zhí)行如果一直調(diào)用來綁定事件的話,內(nèi)存開銷會很大。最后完整代碼請看完

前言:
看兩三遍即可。

在看 jQuery 源碼時,發(fā)現(xiàn)了這段注釋:

  //源碼5235行
  /*
 * Helper functions for managing events -- not part of the public interface.
 * Props to Dean Edwards" addEvent library for many of the ideas.
 */
  jQuery.event = { }

Dean Edwards 的 addEvent.js 庫為 jQuery 的事件綁定提供了很多想法,我們就來看下 2005 年的 addEvent.js 。

〇、先復(fù)習(xí)下 Object 的內(nèi)存地址指向的知識

  let a={ }
  let b=a
  b[0]="111"
  
  console.log(a,"a55") //{0:"111"}

b 改變屬性,a 也會改變,因為 b 與 a 指向同一地址(b=a)

一、addEvent()
作用:
為目標(biāo)元素綁定事件(如 click)

源碼:

  //addEvent即為DOM元素綁定事件

  // a counter used to create unique IDs
  //為每一個事件添加唯一的id
  addEvent.guid = 1;

  function addEvent(element, type, handler) {
    // assign each event handler a unique ID
    //如果用戶自定義的回調(diào)函數(shù)沒有$$guid的話,
    //為每個handler添加唯一的id
    if (!handler.$$guid) handler.$$guid = addEvent.guid++;
    // create a hash table of event types for the element
    //為目標(biāo)元素添加events屬性
    if (!element.events) element.events = {};
    // create a hash table of event handlers for each element/event pair
    //events是目標(biāo)元素綁定的事件的集合
    //第一次使用addEvent綁定往往是undefined
    let handlers = element.events[type];
    if (!handlers) {
      handlers = element.events[type] = {};
      // store the existing event handler (if there is one)
      //handlers的0屬性作為目標(biāo)元素的原生綁定事件
      if (element["on" + type]) {
        handlers[0] = element["on" + type];
      }
    }
    // store the event handler in the hash table
    //將每次綁定的事件保存到handler的id屬性中
    handlers[handler.$$guid] = handler;

    // assign a global event handler to do all the work
    //為目標(biāo)元素的原生事件綁定處理程序(handleEvent)
    element["on" + type] = handleEvent;
  }

解析:
注意let handlers = element.events[type],handlers 與 element.events[type] 指向同一地址,接下來都是對 handlers 進(jìn)行操作,實際上也就是對 element.events 進(jìn)行操作

關(guān)鍵!
addEvent 的目的是讓目標(biāo)元素的結(jié)構(gòu)如下:

element:{
  //依次執(zhí)行了 click 對象里的每個 handler
  onclick:handleEvent(MouseEvent)
  events:{
    click:{
      // 如果先onclick了,就會在這里
      // 0 : onclick(也就是 function (e) {console.log("原生點擊了one")})
      1 : handler(也就是 function(){console.log("點擊了one")}  )
      2 : handler ( xxx )
      3 : ...
     .. : ...    
    },
    foucus:{
      
    }, 
    ..... :{
    
    }

  }
}

注意里面的注釋。
(1)可以看到通過 addEvent 綁定的"click"事件并不是真的綁定在 element 上,而是把綁定的事件處理程序(handler)都放到了 element 的 events 上,即綁定事件和目標(biāo)元素的分離

(2)由 handleEvent 來統(tǒng)一執(zhí)行 click 事件

二、handleEvent()
作用:
執(zhí)行事件的處理程序

源碼:

  //執(zhí)行事件的處理程序
  function handleEvent(event) {
    // grab the event object (IE uses a global event object)
    console.log(event,"event55")
    //event即MouseEvent,原生的鼠標(biāo)事件集合
    event = event || window.event;
    // get a reference to the hash table of event handlers
    //找到相同事件的處理程序
    //注意這個this,指的是目標(biāo)元素
    //找到handlers集合
    let handlers = this.events[event.type];
    // execute each event handler

    //依次執(zhí)行事件的處理程序
    for (let i in handlers) {
      this.$$handleEvent = handlers[i];
      this.$$handleEvent(event);
    }
  }

解析:
(1)看到上面的關(guān)鍵,再看 handleEvent 就簡單地多,就是把 element->events->click 里的事件處理程序都執(zhí)行下

(2)主要看for 里面,多了個handlers 和 handleEvent,我感覺是多余的(不知道下面說的對不對,因為想到了中學(xué)解數(shù)學(xué)題,當(dāng)你覺得題干中的條件你用不到時,往往是自己想錯了),因為直接這么寫就好了啊:

寫法一:

  function handleEvent(event) {
    event = event || window.event;
    for (let i in this.events[event.type]) {
      this.events[event.type][i](event)
    }
 }

寫法二:

  function handleEvent(event) {
    event = event || window.event;
    let handlers = this.events[event.type];
    for (let i in handlers) {
      handlers[i].call(this,event)
    }
 }

根據(jù)this誰調(diào)用的,this就是誰的原則,那么handleEvent thiselement["on"+type],即element.onclick在調(diào)用handleEvent 方法,既然是element的屬性onclick在調(diào)用的話,那么執(zhí)行的上下文就是element,thiselement

Dean Edwards用this.$$handleEvent來執(zhí)行handler,目的也是保證正確的作用域,即this

三、removeEvent

  //移除監(jiān)聽事件
  function removeEvent(element, type, handler) {
    // delete the event handler from the hash table
    console.log(handler,"handler52")
    if (element.events && element.events[type]) {
      delete element.events[type][handler.$$guid];
    }
  }

注意:不把自定義事件包成一個變量,是移除不了監(jiān)聽事件的:

  let one=document.querySelector("#one")
  addEvent(one,"click",function () {
    console.log("點擊了one")
  })
  removeEvent(one,"click",function () {
    console.log("點擊了one")
  })

寫成這樣才可以:

  let one=document.querySelector("#one")
  let handler=function () {
    console.log("點擊了one")
  }
  addEvent(one,"click",handler)
  removeEvent(one,"click",handler)

四、實驗

干我
let one=document.querySelector("#one") one.onclick=function (e) { console.log("原生點擊了one") } addEvent(one,"click",function () { console.log("點擊了one") })

輸出:原生點擊了one 點擊了one

干我
let one=document.querySelector("#one") addEvent(one,"click",function () { console.log("點擊了one") }) one.onclick=function (e) { console.log("原生點擊了one") }

輸出:原生點擊了one ,原因是后面的 one.onclick 覆蓋了 addEvent() 里的事件綁定

當(dāng)然 jQuery 是都會觸發(fā)的。

五、內(nèi)存泄漏
簡單說:
element只綁定一次onclick,只綁定一次events。
并通過guid來為每一個handler定一個id,然后依次添加進(jìn)events.click中,并通過onclick執(zhí)行

如果一直調(diào)用onclick來綁定事件的話,內(nèi)存開銷會很大。

最后:
完整代碼請看https://github.com/AttackXiaoJinJin/jQueryExplain/blob/master/addEvent.js.html

(完)

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/104420.html

相關(guān)文章

  • Flink Metrics 源碼解析

    摘要:有如下模塊源碼解析源碼解析源碼解析源碼解析源碼解析源碼解析源碼解析源碼解析源碼解析使用和監(jiān)控和博客從到學(xué)習(xí)介紹從到學(xué)習(xí)上搭建環(huán)境并構(gòu)建運行簡單程序入門從到學(xué)習(xí)配置文件詳解從到學(xué)習(xí)介紹從到學(xué)習(xí)如何自 Flink Metrics 有如下模塊: Flink Metrics 源碼解析 —— Flink-metrics-core Flink Metrics 源碼解析 —— Flink-metr...

    sshe 評論0 收藏0
  • Flink 源碼解析 —— 深度解析 Flink Checkpoint 機(jī)制

    摘要:機(jī)制博客從到學(xué)習(xí)介紹從到學(xué)習(xí)上搭建環(huán)境并構(gòu)建運行簡單程序入門從到學(xué)習(xí)配置文件詳解從到學(xué)習(xí)介紹從到學(xué)習(xí)如何自定義從到學(xué)習(xí)介紹從到學(xué)習(xí)如何自定義從到學(xué)習(xí)轉(zhuǎn)換從到學(xué)習(xí)介紹中的從到學(xué)習(xí)中的幾種詳解從到學(xué)習(xí)讀取數(shù)據(jù)寫入到從到學(xué)習(xí)項目如何運行從 Flink Checkpoint 機(jī)制 https://t.zsxq.com/ynQNbeM 博客 1、Flink 從0到1學(xué)習(xí) —— Apache Fl...

    0x584a 評論0 收藏0
  • Flink 源碼解析 —— 深度解析 Flink 序列化機(jī)制

    摘要:序列化機(jī)制博客從到學(xué)習(xí)介紹從到學(xué)習(xí)上搭建環(huán)境并構(gòu)建運行簡單程序入門從到學(xué)習(xí)配置文件詳解從到學(xué)習(xí)介紹從到學(xué)習(xí)如何自定義從到學(xué)習(xí)介紹從到學(xué)習(xí)如何自定義從到學(xué)習(xí)轉(zhuǎn)換從到學(xué)習(xí)介紹中的從到學(xué)習(xí)中的幾種詳解從到學(xué)習(xí)讀取數(shù)據(jù)寫入到從到學(xué)習(xí)項目如何 Flink 序列化機(jī)制 https://t.zsxq.com/JaQfeMf 博客 1、Flink 從0到1學(xué)習(xí) —— Apache Flink 介紹 2...

    y1chuan 評論0 收藏0
  • Flink Clients 源碼解析

    摘要:模塊中的類結(jié)構(gòu)如下博客從到學(xué)習(xí)介紹從到學(xué)習(xí)上搭建環(huán)境并構(gòu)建運行簡單程序入門從到學(xué)習(xí)配置文件詳解從到學(xué)習(xí)介紹從到學(xué)習(xí)如何自定義從到學(xué)習(xí)介紹從到學(xué)習(xí)如何自定義從到學(xué)習(xí)轉(zhuǎn)換從到學(xué)習(xí)介紹中的從到學(xué)習(xí)中的幾種詳解從到學(xué)習(xí)讀取數(shù)據(jù)寫入到從到學(xué) Flink-Client 模塊中的類結(jié)構(gòu)如下: https://t.zsxq.com/IMzNZjY showImg(https://segmentfau...

    xiao7cn 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<