一步步帶你解讀redux源碼

小白帶你一步步走入redux的源碼(一、createStore)

  • Redux 是 JavaScript 狀態容器, 提供可預測化的狀態管理。redux 其實說白就是一個狀態管理存儲

- 下面是一個簡單的計數器例子,這裏寫了一個增長減數字相加的問題
複製代碼
<div id="counter">
      <div id="counterValue"></div>
      <button id="incrementBtn">+</button>
      <button id="decrementBtn">-</button>
  </div>
複製代碼
  • 首先帶你入門寫個簡單的使用的例子,下面這部分是JS的引用寫法
// 引入了redux ,調用了createStore這個方法
  import {createStore} from "redux"
  let initState = 0;
  // 定義了兩個獨一無二的類型 Symbol 
  const INCREMENT = Symbol.for('INCREMENT')
  const DECREMENT = Symbol.for('DECREMENT')
  //  用來表示動做類型reducer接收兩個參數,一個是狀態,另一個是觸發的行爲
  // reduce 就是根據觸發行爲的不一樣來返回對應的狀態
  function reducer(state =initState ,action){
      console.log(action)
      switch(action.type){
          case INCREMENT:
              return state+1;
          case DECREMENT:
              return state-1;  
          default:
              return state;          
      }
  }
  // 新老狀態對比而後生成新的狀態
  let store = createStore(reducer)
  let state = store.getState()
  console.log(state)
  let counterValue = document.getElementById("counterValue")
  let incrementBtn = document.getElementById("incrementBtn")
  let decrementBtn = document.getElementById("decrementBtn")
  
  function render(){
      counterValue.innerHTML = store.getState()
  }
  // 能夠手動訂閱更新,也能夠事件綁定到視圖層。
  store.subscribe(render)
  incrementBtn.addEventListener("click",function(){
      console.log(1111)
      store.dispatch({type:INCREMENT,data:99})
      
  })
  decrementBtn.addEventListener("click",function(){
      store.dispatch({type:DECREMENT})
  })
複製代碼
  • 能夠看看上面例子git

  • 在上面的例子中咱們引入了redux ,其中運用了幾個API,在上述例子中獲得了引用,那麼咱們能夠來看看這幾個api在源碼是怎麼樣?是如何暴露出來的?github

    • 一、createStore
    • 二、getState
    • 三、dispatch
    • 四、subscribe
  • 這是github上的源碼目錄,目錄文件不是不少,第一篇首先分析的是入口redux的createStore.js redux

那麼咱們再來看看createStore這個api,能夠看到上述例子有這麼一段代碼,咱們知道createStore 是一個函數,而且他返回了一個對象store,也就是咱們常說的存儲狀態的倉庫api

let store = createStore(reducer)
 let state = store.getState()
複製代碼
  • 如今點進去看createStore.js,滑到源碼最底端,能夠清晰的看到createStore方法暴漏出了五個api,前面三個是咱們平常項目中經常使用的方法,看到這裏,其實咱們就能想到就是執行createStore方法時,會返回一個對象,這個對象上包含這五個屬性。

以下圖,如今讓咱們繼續深刻下去,能夠看到createStore這個函數接收三個參數,那麼這時候咱們內心確定在想三個參數分別幹嗎用的呢?咱們先把它們列出來,在逐一分析每一個參數的含義bash

  • reducer
  • preloadedState
  • enhancer

  • reducer相信你們很常見,它爲了描述 action 如何改變 state tree , 就是處理action的reducer的處理函數, reducers是一個純函數,接收參數state和action。只須要根據action,返回對應的state,並且必需要有返回。
function reducer(state =initState ,action){
            console.log(action)
            switch(action.type){
                case INCREMENT:
                    return state+1;
                case DECREMENT:
                    return state-1;  
                default:
                    return state;          
            }
        }
複製代碼
  • preloadedState:這個就是初始化的狀態state,能夠傳一個初始的值進來

看着這裏,咱們就會想,createStore傳入的的初始狀態和reducer傳入的初始狀態哪一個優先級高?

  • enhancer:這個是createStore的加強器。你能夠選擇性的傳入一個加強函 數取加強 store,例如中間件,時間旅行,持久化。這 redux 惟一一個自帶的 加強器是的 applyMiddleware

寫了這麼多,首先咱們來看看他的第一個api,store.getState()併發

  • 經過store.getState()咱們能夠獲取store裏面存儲的狀態,官方源碼,能夠看到只有短短十幾行代碼就實現了getState方法,而且返回了一個當前的狀態currentState,
function getState() {
    if (isDispatching) {
      throw new Error(
        'You may not call store.getState() while the reducer is executing. ' +
          'The reducer has already received the state as an argument. ' +
          'Pass it down from the top reducer instead of reading it from the store.'
      )
    }
    return currentState
  }
複製代碼

其實前面那個判斷只是判斷當reduce執行的時候不會進行獲取狀態,防止併發,若是把這個判斷刪掉,其實真正有用的就只有一行代碼,也便是執行getState()方法 返回一個狀態app

function getState() {
    return currentState
  }
複製代碼

currentState狀態是如何獲取的呢?

  • 在源碼中咱們只能夠看到這一句話,而這個preloadedState是createStore裏傳入進來的, 因此若是當你沒有執行觸發action的行爲以前,執行store.getState()直接獲取的是傳入的初始化狀態
let currentState = preloadedState 
複製代碼

那第二個問題要考慮的就是在哪裏改變這個狀態的呢,由於咱們在項目中但是有需求想要去改變狀態的,而不僅是存着它們,當祖宗同樣供着,那樣消耗也會很大...如今讓咱們繼續追蹤,redux 究竟是如何進行狀態的改變?函數

function dispatch(action) {
    currentState = currentReducer(currentState, action)
    return action
  }
複製代碼

如上述例子,能夠看到源碼中這麼一段代碼,我進行簡單的刪減,只留下了這三行代碼,從這三行代碼咱們就能夠看出來不少問題。ui

  • 首先能夠看出currentState是在dispatch方法裏執行而後進行獲取值的,而且dispatch接收一個action函數
  • 這就能夠得出咱們改變狀態的惟一途徑是必須出發一個action 也便是執行dispatch(action)這個方法,稍後咱們在解讀dispatch
  • 而後currentState 是執行currentReducer(currentState, action)這個方法以後返回的值?
  • 那麼這個currentReducer(currentState, action)又是幹嗎的呢?

篇幅不易過長,下篇再繼續寫@--@ 創做不易,歡迎各位打賞@--@也能夠關注本人公衆號

相關文章
相關標籤/搜索