1. 程式人生 > >react中的setState的使用和深入理解

react中的setState的使用和深入理解

      前端框架從MVC過渡到MVVM。從DOM操作到資料驅動,一直在不斷的進步著,提升著,

      angular中用的是watcher物件,vue是觀察者模式,react就是state了,他們各有各的特點,沒有好壞之分,只有需求不同而選擇不同。

 

今天就著重詳細的隨手寫點我對react中state的理解:

      React通過管理狀態實現對元件的管理,通過this.state()方法更新state。當this.setState()被呼叫的時候,React會重新呼叫render方法來重新渲染UI。

     

在說setstate這個磨人的小妖精之前,不得不先說一下state這個小可愛了

      定義一個合適的State,是正確建立元件的第一步。因為有一些變數不需要響應式的使用,如果使用了state,就會給這個變數增加一些響應式掛載,要時            刻 記得做到完美  ^-^ 

  判斷是否可以做為一個state的條件:

        1、變數如果是通過props從父元件中獲取,就不是一個狀態

        2、如果這個變數可以通過其他的狀態state或者屬性props 通過資料處理得到,就不是一個狀態

  3、如果變數在render中沒有使用到,那就不是一個state

        4、變數在整個生命週期中都保持不變時,也不是一個狀態 

 其實使用的時候最多的使用到的就是state和props,他們兩個是有很大的區別的,最主要的區別就是:

  State是可變的,是元件內部維護的一組用於反映元件UI變化的狀態集合;

  而Props對於使用它的元件來說,是隻讀的,要想修改Props,只能通過該元件的父元件修改。在元件狀態上移的場景中,父元件正是通過子元件的Props,          傳遞給子元件其所需要的狀態。

 

  在使用state的時候, 如果我們企圖直接修改state中的某一個值之後直接列印(使用)他,就會發現,他其實並沒有改變。

  就像下面的例子,企圖通過點選事件之後就使用修改之後的state的值,但是會發state中的並沒有被立即修改,還是原先的值,我們都知道那是因為     setState就相當於是一個非同步操作,不能立即被修改

     

       那麼我們也都知道為了解決上面的問題會有很多方法例如:

  方法一:

  

       這個回撥函式會在修改了state之後才會執行,這就就可以happy的使用修改之後的state的值了

       方法二:

     

       操作非同步函式,用的最舒服的還是async / await 啦

  當然還有很多其他的解決辦法啦。。。。。。。。只是我會比較常用這兩種方法而已

      

      在使用setState的時候,有兩種格式;

     第一種setstate()格式  第一個引數是一個物件,第二個引數是一個回撥函式,這個回撥函式是在setstate執行完並頁面渲染了之後再執行

    

     但是這種修改的方式不穩妥,因為是直接修改,我還是比較喜歡使用第二種格式

    setstate的第二種格式,接收一個回撥函式,而不是一個物件,這個回撥函式有兩個引數,

    一個是接收前一個狀態值作為第一個引數,並將更新後的值作為第二個引數

    

     這種寫法在這個例子裡有點大材小用了,但是在處理複雜資料和邏輯的時候會特別好用 !

     

 總的來說setstate這個磨人的小妖精就和Vue中的資料響應一樣,

 在Vue中,

Vue官網上偷的圖。。。。。。。。。。

元件、函式等渲染---->建立一個虛擬DOM樹------->當data、computed、props改變時會引起頁面的重新整理--------watcher檢測變化,當變化以後不會 立  即渲染,會有一個佇列,只要觀察到資料變化,Vue 將開啟一個佇列,並緩衝在同一事件迴圈中發生的所有資料改變。如果同一個 watcher 被多次觸           發, 只會被推入到佇列中一次。這種在緩衝時去除重複資料對於避免不必要的計算和 DOM 操作上非常重要。然後,在下一個的事件迴圈“tick”中,Vue 刷          新佇列並執行實際 (已去重的) 工作。   

 

在react中

 可以看出在react中也是和Vue中的一樣,state的值在修改了之後並不會立即被修改,而是也有一個類似的佇列,setState通過一個佇列機制實現state的更新。當執行setState時,會把需要更新的state合併後放入狀態佇列,而不會立刻更新this.state,利用這個佇列機制可以高效的批量的更新state。

 

 真是一個神奇的方法,很喜歡這個可以高效批量更新state的機制,於是就去瞅了瞅setState的原始碼,想看一下react是怎麼構造出setState這個磨人的小妖精的

 

這個構造小妖精的過程也是磨人的。。。。。。理了好久才理清。。。。

 

 它的主要流程如下:

   1、當呼叫setState時,實際上會執行enqueueSetState方法,並對partialState以及_pendingStateQueue更新佇列進行合併,最終通過enqueueUpdate執行state更新

   2、 如果元件當前正處於update事務中,則先將Component存入dirtyComponent中。否則呼叫batchedUpdates處理。

而performUpdateIfNecessary方法獲取_pendingElement、_pendingStateQueue、_pendingForceUpdate,並呼叫reciveComponent和updateComponent方法進行元件更新。
   3、batchedUpdates發起一次transaction.perform()事務
   4、開始執行事務初始化,執行,結束三個階段
           初始化:事務初始化階段沒有註冊方法,故無方法要執行
            執行:執行setSate時傳入的callback方法,一般不會傳callback引數
             結束:更新isBatchingUpdates為false,並執行FLUSH_BATCHED_UPDATES這個wrapper中的close方法
     5、FLUSH_BATCHED_UPDATES在close階段,會迴圈遍歷所有的dirtyComponents,呼叫updateComponent重新整理元件,並執行它的pendingCallbacks, 也就是setState中設定的callback。

 

 

 

 原始碼部分有空補上。。。。。。