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

資訊專欄INFORMATION COLUMN

React事件機(jī)制

lavnFan / 3260人閱讀

摘要:注冊(cè)事件的回調(diào)函數(shù)由來(lái)統(tǒng)一管理,根據(jù)事件的類型和組件標(biāo)識(shí)為唯一標(biāo)識(shí)事件并進(jìn)行存儲(chǔ)。利用中注入的例如會(huì)將原生的事件轉(zhuǎn)化成合成的事件,然后批量執(zhí)行存儲(chǔ)的回調(diào)函,回調(diào)函數(shù)的執(zhí)行分為兩步,第一步是將所有的合成事件放到事件隊(duì)列里面,第二步是逐個(gè)執(zhí)行。

  最近在閱讀《深入React技術(shù)?!芬粫?,發(fā)現(xiàn)了之前使用React中并沒(méi)有注意到的React事件與瀏覽器原生事件之間的區(qū)別,鑒于好久已經(jīng)沒(méi)有寫東西了,就想寫一下關(guān)于React事件的文章。
  首先我們舉個(gè)例子,如果我們需要實(shí)現(xiàn)一個(gè)組件,這個(gè)組件點(diǎn)擊按鈕會(huì)顯示一個(gè)二維碼,點(diǎn)擊二維碼之外的區(qū)域可以隱藏二維碼,但是點(diǎn)擊二維碼本身卻不會(huì)關(guān)閉,代碼如下:

//代碼來(lái)源于《深入React技術(shù)棧》2.1.4節(jié)
class QrCode extends Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
    this.handleClickQr = this.handleClickQr.bind(this);
    this.state = {
      active: false,
    };
  }
  
  componentDidMount() {
    document.body.addEventListener("click", e => {
      this.setState({
        active: false,
      });
    });
  }

  componentWillUnmount() {
    document.body.removeEventListener("click");
  }
  
  handleClick() {
    this.setState({
      active: !this.state.active,
    });
  }
  
  handleClickQr(e) {
    e.stopPropagation();
  }

  render() {
    return (
      
); } }

  上面代碼從感官上感覺(jué)確實(shí)可以實(shí)現(xiàn)要求的組件,但事實(shí)上我們運(yùn)行上述代碼可以發(fā)現(xiàn),點(diǎn)擊二維碼本身也會(huì)導(dǎo)致二維碼的隱藏,現(xiàn)在就有意思了,我們來(lái)仔細(xì)分析一下。
  其實(shí)React事件并沒(méi)有原生的綁定在真實(shí)的DOM上,而是使用了行為委托方式實(shí)現(xiàn)事件機(jī)制。
  

  如上圖所示,在JavaScript中,事件的觸發(fā)實(shí)質(zhì)上是要經(jīng)過(guò)三個(gè)階段:事件捕獲、目標(biāo)對(duì)象本身的事件處理和事件冒泡,假設(shè)在div中觸發(fā)了click事件,實(shí)際上首先經(jīng)歷捕獲階段會(huì)由父級(jí)元素將事件一直傳遞到事件發(fā)生的元素,執(zhí)行完目標(biāo)事件本身的處理事件后,然后經(jīng)歷冒泡階段,將事件從子元素向父元素冒泡。正因?yàn)槭录贒OM的傳遞經(jīng)歷這樣一個(gè)過(guò)程,從而為行為委托提供了可能。通俗地講,行為委托的實(shí)質(zhì)就是將子元素事件的處理委托給父級(jí)元素處理。React會(huì)將所有的事件都綁定在最外層(document),使用統(tǒng)一的事件監(jiān)聽(tīng),并在冒泡階段處理事件,當(dāng)掛載或者卸載組件時(shí),只需要在通過(guò)的在統(tǒng)一的事件監(jiān)聽(tīng)位置增加或者刪除對(duì)象,因此可以提高效率。
  并且React并沒(méi)有使用原生的瀏覽器事件,而是在基于Virtual DOM的基礎(chǔ)上實(shí)現(xiàn)了合成事件(SyntheticEvent),事件處理程序接收到的是SyntheticEvent的實(shí)例。SyntheticEvent完全符合W3C的標(biāo)準(zhǔn),因此在事件層次上具有瀏覽器兼容性,與原生的瀏覽器事件一樣擁有同樣的接口,可以通過(guò)stopPropagation()preventDefault()相應(yīng)的中斷。如果需要訪問(wèn)當(dāng)原生的事件對(duì)象,可以通過(guò)引用nativeEvent獲得。
  
  上圖為大致的React事件機(jī)制的流程圖,React中的事件機(jī)制分為兩個(gè)階段:事件注冊(cè)和事件觸發(fā):

事件注冊(cè)  
  React在組件加載(mount)和更新(update)時(shí),其中的ReactDOMComponent會(huì)對(duì)傳入的事件屬性進(jìn)行處理,對(duì)相關(guān)事件進(jìn)行注冊(cè)和存儲(chǔ)。document中注冊(cè)的事件不處理具體的事件,僅對(duì)事件進(jìn)行分發(fā)。ReactBrowserEventEmitter作為事件注冊(cè)入口,擔(dān)負(fù)著事件注冊(cè)和事件觸發(fā)。注冊(cè)事件的回調(diào)函數(shù)由EventPluginHub來(lái)統(tǒng)一管理,根據(jù)事件的類型(type)和組件標(biāo)識(shí)(_rootNodeID)為key唯一標(biāo)識(shí)事件并進(jìn)行存儲(chǔ)。

事件執(zhí)行
  事件執(zhí)行時(shí),document上綁定事件ReactEventListener.dispatchEvent會(huì)對(duì)事件進(jìn)行分發(fā),根據(jù)之前存儲(chǔ)的類型(type)和組件標(biāo)識(shí)(_rootNodeID)找到觸發(fā)事件的組件。ReactEventEmitter利用EventPluginHub中注入(inject)的plugins(例如:SimpleEventPlugin、EnterLeaveEventPlugin)會(huì)將原生的DOM事件轉(zhuǎn)化成合成的事件,然后批量執(zhí)行存儲(chǔ)的回調(diào)函,回調(diào)函數(shù)的執(zhí)行分為兩步,第一步是將所有的合成事件放到事件隊(duì)列里面,第二步是逐個(gè)執(zhí)行。需要注意的是,瀏覽器原生會(huì)為每個(gè)事件的每個(gè)listener創(chuàng)建一個(gè)事件對(duì)象,可以從這個(gè)事件對(duì)象獲取到事件的引用。這會(huì)造成高額的內(nèi)存分配,React在啟動(dòng)時(shí)就會(huì)為每種對(duì)象分配內(nèi)存池,用到某一個(gè)事件對(duì)象時(shí)就可以從這個(gè)內(nèi)存池進(jìn)行復(fù)用,節(jié)省內(nèi)存。

  再回到我們剛開(kāi)始的問(wèn)題,現(xiàn)在看起來(lái)就很沒(méi)有很費(fèi)解了,之所以會(huì)出現(xiàn)上面的問(wèn)題是因?yàn)槲覀兓煊昧薘eact的事件機(jī)制和DOM原生的事件機(jī)制,認(rèn)為通過(guò):

handleClickQr(e) {
    e.stopPropagation();
}

就能阻止原生的事件傳播,其實(shí)在事件委托的情形下是不能實(shí)現(xiàn)這一點(diǎn)的。當(dāng)然解決的辦法也不復(fù)雜,不要將React事件和DOM原生事件混用。

componentDidMount() {
  document.body.addEventListener("click", e => {
    this.setState({
      active: false,
    });
  });
 
  document.querySelector(".code").addEventListener("click", e => {
    e.stopPropagation();
  })
}

componentWillUnmount() {
  document.body.removeEventListener("click");
  document.querySelector(".qr").removeEventListener("click");
}

或者通過(guò)事件原件對(duì)象中的target進(jìn)行判斷:

componentDidMount() {
  document.body.addEventListener("click", e => {
    if (e.target && e.target.matches("div.code")) {
      return;
    }
 
    this.setState({
      active: false,
    });
  });
}

都可以解決異常關(guān)閉的問(wèn)題。

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

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

相關(guān)文章

  • 談?wù)?em>React事件機(jī)制和未來(lái)(react-events)

    摘要:另外第三方也可以通過(guò)的事件插件機(jī)制來(lái)合成自定義事件,盡管很少人這么做。抽象跨平臺(tái)事件機(jī)制。打算干預(yù)事件的分發(fā)。事件是的一個(gè)自定義事件,旨在規(guī)范化表單元素的變動(dòng)事件。 showImg(https://segmentfault.com/img/remote/1460000019961124?w=713&h=307); 當(dāng)我們?cè)诮M件上設(shè)置事件處理器時(shí),React并不會(huì)在該DOM元素上直接綁定...

    TNFE 評(píng)論0 收藏0
  • React深入】React事件機(jī)制

    摘要:給注冊(cè)原生事件回調(diào)為統(tǒng)一的事件分發(fā)機(jī)制。根據(jù)元素唯一標(biāo)識(shí)和事件類型從中取出回調(diào)函數(shù)返回帶有合成事件參數(shù)的回調(diào)函數(shù)總流程將上面的四個(gè)流程串聯(lián)起來(lái)。可見(jiàn),回調(diào)函數(shù)是直接調(diào)用調(diào)用的,并沒(méi)有指定調(diào)用的組件,所以不進(jìn)行手動(dòng)綁定的情況下直接獲取到的是。 關(guān)于React事件的疑問(wèn) 1.為什么要手動(dòng)綁定this 2.React事件和原生事件有什么區(qū)別 3.React事件和原生事件的執(zhí)行順序,可以混...

    philadelphia 評(píng)論0 收藏0
  • 結(jié)合源碼徹底理解 react事件機(jī)制原理 01 - 對(duì)事件機(jī)制的初步理解和驗(yàn)證

    摘要:前言這是事件機(jī)制的第一篇,主要內(nèi)容有表象理解,驗(yàn)證,意義和思考。因?yàn)楹铣墒录挠|發(fā)是基于瀏覽器的事件機(jī)制來(lái)實(shí)現(xiàn)的,通過(guò)冒泡機(jī)制冒泡到最頂層元素,然后再由統(tǒng)一去處理。合成事件的阻止冒泡不會(huì)影響原生事件。 showImg(https://segmentfault.com/img/bVbtvP2?w=800&h=420); 前言 這是 react 事件機(jī)制的第一篇,主要內(nèi)容有:表象理解,驗(yàn)證...

    muddyway 評(píng)論0 收藏0
  • 淺談React事件機(jī)制

    摘要:事件簡(jiǎn)介事件是合成事件,所有事件都自動(dòng)綁定到最外層上。支持事件的冒泡機(jī)制,我們可以使用和來(lái)中斷它。這樣做簡(jiǎn)化了事件處理和回收機(jī)制,效率也有很大提升。事件類型合成事件的事件類型是原生事件類型的一個(gè)子集。 React事件簡(jiǎn)介 React事件是合成事件,所有事件都自動(dòng)綁定到最外層上。因?yàn)閂irtual DOM 在內(nèi)存中是以對(duì)象的形式存在的,所以React 基于 Virtual DOM 實(shí)現(xiàn)了...

    moven_j 評(píng)論0 收藏0
  • 淺談React事件機(jī)制

    摘要:事件簡(jiǎn)介事件是合成事件,所有事件都自動(dòng)綁定到最外層上。支持事件的冒泡機(jī)制,我們可以使用和來(lái)中斷它。這樣做簡(jiǎn)化了事件處理和回收機(jī)制,效率也有很大提升。事件類型合成事件的事件類型是原生事件類型的一個(gè)子集。 React事件簡(jiǎn)介 React事件是合成事件,所有事件都自動(dòng)綁定到最外層上。因?yàn)閂irtual DOM 在內(nèi)存中是以對(duì)象的形式存在的,所以React 基于 Virtual DOM 實(shí)現(xiàn)了...

    MyFaith 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<