どのようにRedux作品?HTMLとpure JSのみ


これはHTMLと純粋なJavaScriptだけでreduxのコード例です.Code sandbox
<!DOCTYPE html>
<html>
  <head>
    <title>Redux basic example</title>
    <script src="https://unpkg.com/redux@latest/dist/redux.min.js"></script>
  </head>
  <body>
    <div>
      <p>
        Clicked: <span id="value">0</span> times
        <button id="increment">+</button>
        <button id="decrement">-</button>
        <button id="incrementIfOdd">Increment if odd</button>
        <button id="incrementAsync">Increment async</button>
      </p>
    </div>
    <script>
      function counter(state, action) {
        if (typeof state === 'undefined') {
          return 0
        }

        switch (action.type) {
          case 'INCREMENT':
            return state + 1
          case 'DECREMENT':
            return state - 1
          default:
            return state
        }
      }

      var store = Redux.createStore(counter)
      var valueEl = document.getElementById('value')

      function render() {
        valueEl.innerHTML = store.getState().toString()
      }

      render()
      store.subscribe(render)

      document.getElementById('increment')
        .addEventListener('click', function () {
          store.dispatch({ type: 'INCREMENT' })
        })

      document.getElementById('decrement')
        .addEventListener('click', function () {
          store.dispatch({ type: 'DECREMENT' })
        })

      document.getElementById('incrementIfOdd')
        .addEventListener('click', function () {
          if (store.getState() % 2 !== 0) {
            store.dispatch({ type: 'INCREMENT' })
          }
        })

      document.getElementById('incrementAsync')
        .addEventListener('click', function () {
          setTimeout(function () {
            store.dispatch({ type: 'INCREMENT' })
          }, 1000)
        })
    </script>
  </body>
</html>
Webページは次のようになります
  • createStore & counterReducer
  • // Counter reducer
    function counterReducer(state, action) {
        if (typeof state === 'undefined') {
            return 0;
        }
        switch (action.type) {
            case 'INCREMENT':
                return state + 1;
            case 'DECREMENT':
                return state - 1;
            default:
                return state;
        }
    }
    // Create store
    var store = Redux.createStore(counterReducer);
    
  • createStore 受信するcounterReducer paramとして機能し、storeというオブジェクトを返します.
  • これはメンタルモデルをクラスとしたCreateStore機能のダイアグラムです.

  • こちらsimplified version of createStore in redux source code :
    function createStore(reducer, initialState) {
      var currentReducer = reducer;
      var currentState = initialState;
      var listeners = [];
      var isDispatching = false;
    
      function getState() {
        return currentState;
      }
    
      function subscribe(listener) {
        listeners.push(listener);
    
        return function unsubscribe() {
          var index = listeners.indexOf(listener);
          listeners.splice(index, 1);
        };
      }
    
      function dispatch(action) {
        if (isDispatching) {
          throw new Error('Reducers may not dispatch actions.');
        }
    
        try {
          isDispatching = true;
          currentState = currentReducer(currentState, action);
        } finally {
          isDispatching = false;
        }
    
        listeners.slice().forEach(listener => listener());
        return action;
      }
    
      function replaceReducer(nextReducer) {
        currentReducer = nextReducer;
        dispatch({ type: '@@redux/INIT' });
      }
    
      dispatch({ type: '@@redux/INIT' });
    
      return { dispatch, subscribe, getState, replaceReducer };
    }
    
  • currentReducer = counterReducer
  • currentState = preloadedSate
  • ストアが作成されるとdispatch アクションタイプ'@@redux/INIT' すべての還元器が初期状態を返すように.場合にcounterReducer , it returns 0
  • 何がディスパッチ機能の内部で起こるか?


    // Dispatch function inside Redux store
    function dispatch(action: A) {    
        currentState = currentReducer(currentState, action)
        const listeners = (currentListeners = nextListeners)
        for (let i = 0; i < listeners.length; i++) {
            const listener = listeners[i]
            listener()
        }
        return action
    }
    
  • 機能currentReducer が呼ばれるcounterReducer
  • アクションタイプ@@redux/INIT and currentState is undefined , so counterReducer リターン0 ストアの初期状態です.
  • さあcurrentState is 0
  • 初期値で状態を更新した後、それを通知するストアを購読しているすべてのリスナを呼び出します.
  • var valueEl = document.getElementById('value')
    
    function render() {
      valueEl.innerHTML = store.getState().toString()
    }
    
    render()
    store.subscribe(render)
    
  • この場合、我々はrender() 関数は、DOM要素を初期値で返し、更新します.
  • 今ブラウザで、私たちは番号を0 図示.
  • アクションが送られるとき、状態を更新する


    document.getElementById('increment')
        .addEventListener('click', function () {
          store.dispatch({ type: 'INCREMENT' })
        })
    
  • ユーザーがボタンをクリックするとき'INCREMENT' 店の還元器と流れについては、上記と同様である.
  • 機能currentReducer0 とアクションの型は'INCREMENT' .
  • だって'INCREMENT' ケースインサイドcounterReducer 機能は、現在の新しい状態に等しい0 + 1 そして、店の状態に戻りました.
  • 次に、それはリスナーに彼らが状態が正常に更新されて知っているように通知します.
  • 現在、我々はクリックします
  • 流れは他のアクションタイプと似ています
  • したがって、これは基本的にどのようにreduxはフードの下で動作します.リアルライフプロジェクトでは、Reduxストアは、複数のreducers and midleware , サードパーティのライブラリは、Reduxワークフローを高める.しかし、そのコアは、それは基本的にどのように動作します!