日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

React-事件机制杂记

發布時間:2024/4/17 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 React-事件机制杂记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前提

最近通過閱讀React官方文檔的事件模塊,有了一些思考和收獲,在這里記錄一下~

調用方法時需要手動綁定this

先從一段官方代碼看起:

代碼中的注釋提到了一句話:

This binding is necessary to make this work in the callback

this的綁定是必須的,其實這一塊是比較容易理解的, 因為這并不是React的一個特殊點, 而是Javascript這門語言的特性。

可以看到,調用的是this.handleClick函數,handleClick函數里面又讀取到了this屬性,但是該函數的調用位置又是在render函數里面,render返回的是一個JSX,最后經過babel編譯成調用React.createElement函數,

在這之前,我們掌握的是this永遠指向的是最后調用它的對象,經過這樣的一個轉換, 實際上this最后指向的是undeined了, 那么調用handleClick函數自然會報錯。

當然,如果你不在函數里面使用this的話,通常會沒事,但并不建議這么做。

關于this的指向與function的原理,推薦閱讀 how functions work in JavaScript

既然知道了是因為this的指向原因而采用綁定的做法,那當然可以用箭頭函數來解決了,箭頭函數中的this是在定義函數的時候綁定,也就是說this是繼承自父執行上下文,如下:

這樣this也能達到我們的預期效果

合成事件SyntheticEvent

先從官方上的一段話看起,他的意思是合成事件是React根據W3C標準定義的,無需擔心瀏覽器之間的差異

Here, e is a synthetic event. React defines these synthetic events according to the W3C spec, so you don’t need to worry about cross-browser compatibility

樣看起來React的合成事件只是兼容瀏覽器? 答案當然是遠遠不止啦!

在探尋其優點之前,我們先看一下其是怎樣的一個機制。

React的事件機制其實網上有很多同學都分析過了, 他并沒有將事件注冊在對應的元素或者組件上面,而是通過委托的方式,將所有的事件都注冊到了document對象上,并統一調用一個dispatch回調函數,其流程圖如下

我們也可以從一個實際的簡單例子看看:

我們把回調函數綁定到了button上,但是在事件上卻沒有看到button元素, 但是卻有document,并且可以看到他的回調函數就是dispatchInteractiveEvent


最后觸發事件的回調函數時,在原生的DOM會傳入一個事件屬性event,但是因為React將 所有事件委托給document處理, 那么這個event就和我們想要的不一樣,如target指向的是document,于是React就有了自己的一個合成事件,通過一個叫SyntheticEvent的基類來生成所需要的事件屬性,并傳入回調函數作為方法。

說到底,React就是把所有事件委托給document處理, 那么這樣做有什么好處:

可以統一在組件掛載和卸載時做處理
只需要注冊一個事件即可,節省內存開銷
可以手動控制事件流程,特別是對state的batch處理(參考React系列的setState)

  • 可以統一在組件掛載和卸載時做處理
  • 只需要注冊一個事件即可,節省內存開銷
  • 可以手動控制事件流程,特別是對state的batch處理(參考React系列的setState)

事件屬性會在事件調用后被回收,即不能異步訪問

老規矩,先上一段代碼:

可以看到在setTimeout函數中,訪問事件屬性是null。這是為啥?

其實這也是合成事件的一個優化手段。 React會在事件調用完成后清理掉屬性,否則每點擊一次就生成一個事件,那么內存的開銷會越來越大,具體的代碼可以在后面的源碼分析中看到:

當然了, React也可以手動設置不回收,如下:

If you want to access the event properties in an asynchronous way, you should call event.persist() on the event

我們可以通過調用event,persist來設置不回收。

事件機制的源碼分析

注冊階段

首先在某一個任務單元fiber調用compeleteWork函數時, React會判斷其是否具有事件屬性, 如果有則調用ensureListeningTo函數

ensureListeningTo函數主要是獲取到document對象, 并調用listenTo函數

listerTo函數 主要是通過調用trapBubbledEvent或者trapCapturedEvent將事件放在document事件上監聽

trapBubbledEvent主要是監聽事件, 但也可以看出, 所有事件最后觸發的都是注冊在document上的dispatch函數

調用階段

dispatch函數, 主要是獲取實際觸發的元素以及對應的fiber, 最后調用batchedUpdates函數, batchedUpdates函數里面的邏輯主要是關于setState的,這里主要是看事件機制, 只要知道最后調用的是handleTopLevel(bookkeeping)就好

handleTopLevel函數主要是拿到需要觸發事件的相關fiber, 并調用runExtractedEventsInBatch函數

extractEvents函數是一個生成React事件的函數,React事件是通過繼承一個通用類SyntheticEvent生成的,如一個鼠標事件的生成

React事件內部做了優化, 只要生成過SyntheticMouseEvent類, 就會再釋放事件的時候將這個類存儲起來,在下一個事件觸發時可以直接使用

React生成事件后, 會調用accumulateTwoPhaseDispatches(event)函數,該函數一直追溯下去, 最后會調用traverseTwoPhase函數,

traverseTwoPhase函數主要是獲取祖先組件的fiber, 并進行捕獲和冒泡的階段處理

accumulateDirectionalDispatches函數相對簡單, 就是把fiber上對應的事件函數賦值給evnet的_dispatchListeners屬性

React事件獲取完成后, 回到runExtractedEventsInBatch函數繼續調用runEventsInBatch(events, false); 函數的中間作了一系列的處理, 但最后執行的是executeDispatchesAndRelease函數

executeDispatchesAndRelease函數會在執行完事件后判斷用戶是否有設置不銷毀事件, 如果沒有, 則銷毀事件并保存事件類, 一個事件類實例一次并重復使用, 這也是為什么官方提到事件屬性只能在當前循環中讀到

繼續往下走, 最后執行的函數是invokeGuardedCallbackDev, 該函數通過注冊一個自定義的元素<react>和自定義的事件, 并觸發它來達到執行回調函數的功能

流程總結

  • 通過Fiber中的屬性, 將事件統一委托 注冊到document上,并為document注冊相應的事件回調函數 dispatch函數。
  • 先獲取實際觸發元素對應的fiber.
  • 生成相應的React事件屬性event,將對應的回調函數賦值給event._dispatchListeners, 將fiber賦值給event._dispatchInstances
  • 通過fiber向上遍歷, 找到所有的祖先fiber, 并按原生事件的機制先捕獲后冒泡的執行事件
  • 注冊一個react節點, 為其注冊一個監聽事件并觸發來執行事件回調函數
  • 最后,根據用戶的設置, 決定是否釋放事件。
  • 總結

    以上是生活随笔為你收集整理的React-事件机制杂记的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 日韩一区二区在线播放 | 日韩图片区 | 国产人成一区二区三区影院 | 精品无码一区二区三区的天堂 | 北岛玲av| 1024精品一区二区三区日韩 | 不卡的日韩av | 伊伊总综合网 | 免费在线观看黄网 | 国内av片| 国产一区二区三区免费视频 | 人人舔人人插 | 国产高清一级片 | 亚洲中文字幕无码av永久 | 成人小说亚洲一区二区三区 | 天天色天天操天天射 | 亚洲免费成人网 | 国产经典三级在线 | 亚洲精品社区 | 四虎av在线播放 | 精品一区二区三区不卡 | 亚洲三区在线观看无套内射 | 激情av在线播放 | 少妇熟女视频一区二区三区 | 欧美成人免费在线 | 日本a级大片 | 91丨九色丨丰满 | 污片免费在线观看 | 精品午夜一区二区三区在线观看 | 国产清纯在线 | 91色| 国产精品无码专区 | 伊人网大 | 成人深夜影院 | 亚洲国产成人精品无码区99 | 国产福利小视频在线观看 | 三级精品在线观看 | 一本之道久久 | 久久精品丝袜高跟鞋 | 免费在线看黄的网站 | 国产欧美亚洲精品 | 原创露脸88av | 中文字幕中文字幕 | 91禁外国网站 | 欧美视频一区二区 | 男人的天堂一级片 | 欧美成人免费观看视频 | 91theporn国产在线观看 | 成年人网站在线免费观看 | 亚洲精品女人 | 在线看黄网址 | 日本公妇乱偷中文字幕 | 欧美激情视频网站 | 中国特级黄色片 | 性生交生活影碟片 | 亚洲日本韩国在线 | 怡红院av亚洲一区二区三区h | 亚洲国产欧美一区二区三区深喉 | 久久在线视频 | 老子影院午夜伦不卡大全 | 亚洲a在线视频 | 中文字幕无码人妻少妇免费 | 亚洲性猛交| 国产美女精品人人做人人爽 | 综合久久99| 免费中文字幕 | 69日本xxxxxxxxx30| 亚洲欧洲精品一区 | 日本涩涩视频 | 灌满闺乖女h高h调教尿h | 99re这里只有精品66 | 日韩黄色av | 国产又黄又湿 | 一区二区福利视频 | 中文字幕第6页 | 国产精品女教师 | 激情黄色小说视频 | 欧美三日本三级少妇三99 | 国产性生活网站 | 丰满人妻一区二区三区无码av | 国产精品一国产精品 | 亚洲码中文 | 亚洲中文无码av在线 | 草草视频网站 | 日本色www| 日韩有码av | 亚洲成人tv | 欧美一区二区免费视频 | 国产一卡二卡三卡四卡 | 欧美中文日韩 | 美女福利视频网 | 国产伦精品一区三区精东 | av网站免费观看 | 自拍偷在线精品自拍偷无码专区 | 久久精品69| 一级特黄色| 国产有码在线 | 色一区二区三区 | 日日碰狠狠添天天爽无码 |