成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

【React深入】React事件機(jī)制

philadelphia / 2323人閱讀

摘要:給注冊(cè)原生事件回調(diào)為統(tǒng)一的事件分發(fā)機(jī)制。根據(jù)元素唯一標(biāo)識(shí)和事件類(lèi)型從中取出回調(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í)行順序,可以混用嗎

4.React事件如何解決跨瀏覽器兼容

5.什么是合成事件

下面是我閱讀過(guò)源碼后,將所有的執(zhí)行流程總結(jié)出來(lái)的流程圖,不會(huì)貼代碼,如果你想閱讀代碼看看具體是如何實(shí)現(xiàn)的,可以根據(jù)流程圖去源碼里尋找。

事件注冊(cè)

組件裝載 / 更新。

通過(guò)lastProps、nextProps判斷是否新增、刪除事件分別調(diào)用事件注冊(cè)、卸載方法。

調(diào)用EventPluginHubenqueuePutListener進(jìn)行事件存儲(chǔ)

獲取document對(duì)象。

根據(jù)事件名稱(如onClick、onCaptureClick)判斷是進(jìn)行冒泡還是捕獲。

判斷是否存在addEventListener方法,否則使用attachEvent(兼容IE)。

document注冊(cè)原生事件回調(diào)為dispatchEvent(統(tǒng)一的事件分發(fā)機(jī)制)。

事件存儲(chǔ)

EventPluginHub負(fù)責(zé)管理React合成事件的callback,它將callback存儲(chǔ)在listenerBank中,另外還存儲(chǔ)了負(fù)責(zé)合成事件的Plugin。

EventPluginHubputListener方法是向存儲(chǔ)容器中增加一個(gè)listener。

獲取綁定事件的元素的唯一標(biāo)識(shí)key。

callback根據(jù)事件類(lèi)型,元素的唯一標(biāo)識(shí)key存儲(chǔ)在listenerBank中。

listenerBank的結(jié)構(gòu)是:listenerBank[registrationName][key]

例如:

{
    onClick:{
        nodeid1:()=>{...}
        nodeid2:()=>{...}
    },
    onChange:{
        nodeid3:()=>{...}
        nodeid4:()=>{...}
    }
}
事件觸發(fā) / 執(zhí)行

這里的事件執(zhí)行利用了React的批處理機(jī)制,在前一篇的【React深入】setState執(zhí)行機(jī)制中已經(jīng)分析過(guò),這里不再多加分析。

觸發(fā)document注冊(cè)原生事件的回調(diào)dispatchEvent

獲取到觸發(fā)這個(gè)事件最深一級(jí)的元素

例如下面的代碼:首先會(huì)獲取到this.child

      
this.parent = ref}>
this.child = ref}> test

遍歷這個(gè)元素的所有父元素,依次對(duì)每一級(jí)元素進(jìn)行處理。

構(gòu)造合成事件。

將每一級(jí)的合成事件存儲(chǔ)在eventQueue事件隊(duì)列中。

遍歷eventQueue。

通過(guò)isPropagationStopped判斷當(dāng)前事件是否執(zhí)行了阻止冒泡方法。

如果阻止了冒泡,停止遍歷,否則通過(guò)executeDispatch執(zhí)行合成事件。

釋放處理完成的事件。

react在自己的合成事件中重寫(xiě)了stopPropagation方法,將isPropagationStopped設(shè)置為true,然后在遍歷每一級(jí)事件的過(guò)程中根據(jù)此遍歷判斷是否繼續(xù)執(zhí)行。這就是react自己實(shí)現(xiàn)的冒泡機(jī)制。

合成事件

調(diào)用EventPluginHubextractEvents方法。

循環(huán)所有類(lèi)型的EventPlugin(用來(lái)處理不同事件的工具方法)。

在每個(gè)EventPlugin中根據(jù)不同的事件類(lèi)型,返回不同的事件池。

在事件池中取出合成事件,如果事件池是空的,那么創(chuàng)建一個(gè)新的。

根據(jù)元素nodeid(唯一標(biāo)識(shí)key)和事件類(lèi)型從listenerBink中取出回調(diào)函數(shù)

返回帶有合成事件參數(shù)的回調(diào)函數(shù)

總流程

將上面的四個(gè)流程串聯(lián)起來(lái)。

為什么要手動(dòng)綁定this

通過(guò)事件觸發(fā)過(guò)程的分析,dispatchEvent調(diào)用了invokeGuardedCallback方法。

function invokeGuardedCallback(name, func, a) {
  try {
    func(a);
  } catch (x) {
    if (caughtError === null) {
      caughtError = x;
    }
  }
}

可見(jiàn),回調(diào)函數(shù)是直接調(diào)用調(diào)用的,并沒(méi)有指定調(diào)用的組件,所以不進(jìn)行手動(dòng)綁定的情況下直接獲取到的thisundefined。

這里可以使用實(shí)驗(yàn)性的屬性初始化語(yǔ)法 ,也就是直接在組件聲明箭頭函數(shù)。箭頭函數(shù)不會(huì)創(chuàng)建自己的this,它只會(huì)從自己的作用域鏈的上一層繼承this。因此這樣我們?cè)?b>React事件中獲取到的就是組件本身了。

和原生事件有什么區(qū)別

React 事件使用駝峰命名,而不是全部小寫(xiě)。

通過(guò) JSX , 你傳遞一個(gè)函數(shù)作為事件處理程序,而不是一個(gè)字符串。

例如,HTML

React 中略有不同:

另一個(gè)區(qū)別是,在 React 中你不能通過(guò)返回 false 來(lái)阻止默認(rèn)行為。必須明確調(diào)用 preventDefault 。

由上面執(zhí)行機(jī)制我們可以得出:React自己實(shí)現(xiàn)了一套事件機(jī)制,自己模擬了事件冒泡和捕獲的過(guò)程,采用了事件代理,批量更新等方法,并且抹平了各個(gè)瀏覽器的兼容性問(wèn)題。

React事件和原生事件的執(zhí)行順序
  componentDidMount() {
    this.parent.addEventListener("click", (e) => {
      console.log("dom parent");
    })
    this.child.addEventListener("click", (e) => {
      console.log("dom child");
    })
    document.addEventListener("click", (e) => {
      console.log("document");
    })
  }

  childClick = (e) => {
    console.log("react child");
  }

  parentClick = (e) => {
    console.log("react parent");
  }

  render() {
    return (
      
this.parent = ref}>
this.child = ref}> test
) }

執(zhí)行結(jié)果:

由上面的流程我們可以理解:

react的所有事件都掛載在document

當(dāng)真實(shí)dom觸發(fā)后冒泡到document后才會(huì)對(duì)react事件進(jìn)行處理

所以原生的事件會(huì)先執(zhí)行

然后執(zhí)行react合成事件

最后執(zhí)行真正在document上掛載的事件

react事件和原生事件可以混用嗎?

react事件和原生事件最好不要混用。

原生事件中如果執(zhí)行了stopPropagation方法,則會(huì)導(dǎo)致其他react事件失效。因?yàn)樗性氐氖录o(wú)法冒泡到document上。

由上面的執(zhí)行機(jī)制不難得出,所有的react事件都將無(wú)法被注冊(cè)。

合成事件、瀏覽器兼容
  function handleClick(e) {
    e.preventDefault();
    console.log("The link was clicked.");
  }
這里, e 是一個(gè)合成的事件。 React 根據(jù) W3C 規(guī)范 定義了這個(gè)合成事件,所以你不需要擔(dān)心跨瀏覽器的兼容性問(wèn)題。

事件處理程序?qū)鬟f SyntheticEvent 的實(shí)例,這是一個(gè)跨瀏覽器原生事件包裝器。 它具有與瀏覽器原生事件相同的接口,包括 stopPropagation()preventDefault() ,在所有瀏覽器中他們工作方式都相同。

每個(gè) SyntheticEvent 對(duì)象都具有以下屬性:

boolean bubbles
boolean cancelable
DOMEventTarget currentTarget
boolean defaultPrevented
number eventPhase
boolean isTrusted
DOMEvent nativeEvent
void preventDefault()
boolean isDefaultPrevented()
void stopPropagation()
boolean isPropagationStopped()
DOMEventTarget target
number timeStamp
string type

React合成的SyntheticEvent采用了事件池,這樣做可以大大節(jié)省內(nèi)存,而不會(huì)頻繁的創(chuàng)建和銷(xiāo)毀事件對(duì)象。

另外,不管在什么瀏覽器環(huán)境下,瀏覽器會(huì)將該事件類(lèi)型統(tǒng)一創(chuàng)建為合成事件,從而達(dá)到了瀏覽器兼容的目的。

推薦閱讀

【React深入】setState的執(zhí)行機(jī)制

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/102379.html

相關(guān)文章

  • 深入React知識(shí)點(diǎn)整理(一)

    摘要:以我自己的理解,函數(shù)式編程就是以函數(shù)為中心,將大段過(guò)程拆成一個(gè)個(gè)函數(shù),組合嵌套使用。越來(lái)越多的跡象表明,函數(shù)式編程已經(jīng)不再是學(xué)術(shù)界的最?lèi)?ài),開(kāi)始大踏步地在業(yè)界投入實(shí)用。也許繼面向?qū)ο缶幊讨?,函?shù)式編程會(huì)成為下一個(gè)編程的主流范式。 使用React也滿一年了,從剛剛會(huì)使用到逐漸探究其底層實(shí)現(xiàn),以便學(xué)習(xí)幾招奇技淫巧從而在自己的代碼中使用,寫(xiě)出高效的代碼。下面整理一些知識(shí)點(diǎn),算是React看書(shū)...

    Gilbertat 評(píng)論0 收藏0
  • 談?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事件機(jī)制

    摘要:注冊(cè)事件的回調(diào)函數(shù)由來(lái)統(tǒng)一管理,根據(jù)事件的類(lèi)型和組件標(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ù)?!芬粫?shū)中,發(fā)現(xiàn)了之前使用React中并沒(méi)有注意到的React事件與瀏覽器原生事件之間的區(qū)別,鑒于好久已經(jīng)沒(méi)有寫(xiě)...

    lavnFan 評(píng)論0 收藏0
  • React深入】setState的執(zhí)行機(jī)制

    摘要:調(diào)用事務(wù)的方法,遍歷待更新組件隊(duì)列依次執(zhí)行更新。執(zhí)行生命周期,根據(jù)返回值判斷是否要繼續(xù)更新。三總結(jié)鉤子函數(shù)和合成事件中在的生命周期和合成事件中,仍然處于他的更新機(jī)制中,這時(shí)為。這時(shí)將執(zhí)行之前累積的。 一.幾個(gè)開(kāi)發(fā)中經(jīng)常會(huì)遇到的問(wèn)題 以下幾個(gè)問(wèn)題是我們?cè)趯?shí)際開(kāi)發(fā)中經(jīng)常會(huì)遇到的場(chǎng)景,下面用幾個(gè)簡(jiǎn)單的示例代碼來(lái)還原一下。 1.setState是同步還是異步的,為什么有的時(shí)候不能立即拿到更新結(jié)...

    zombieda 評(píng)論0 收藏0
  • 深入react技術(shù)棧》學(xué)習(xí)筆記(三)漫談React

    摘要:前言接下來(lái)讓我們進(jìn)入新的章節(jié)漫談。正文一事件系統(tǒng)的事件系統(tǒng)事件系統(tǒng)符合標(biāo)準(zhǔn),不存在任何兼容性問(wèn)題,并且與原生的瀏覽器事件一樣有同樣的接口。所有的事件都自動(dòng)綁定到最外層。組織事件冒泡的行為只適用于合成系統(tǒng)中,且沒(méi)辦法阻止原生事件冒泡。 前言 接下來(lái)讓我們進(jìn)入新的章節(jié):漫談React。本篇文章主要講React事件系統(tǒng)和表單操作。 正文 一:事件系統(tǒng) 1.react的事件系統(tǒng)react事件系...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<