Vanilla Redux 示例(不含 React 或其他)

你可以點選此處檢視正在執行的演示。

HTML:

<p>
  <span>Counter State</span><br />
  (<em>Will increase each minute</em>):
  <p>
    <span id="counter-state" style="font-weight: bolder"></span>
  </p>
</p>

<p>
  <button id="increment-action">+ Increase +</button>
  <button id="decrement-action">- Decrease -</button>
</p>

REDUX LOGIC:

// ------------------------ reducer helpers ------------------------
let reducers = {}

let addReducer = (reducers, actionType, reducer) =>
  reducers[actionType] = (state, action) => {
    if (action.type == actionType) {
      return reducer(state, action)
    }
  }

let reducer = (state, action) => {
  if (reducers[action.type]) {
    return reducers[action.type](state, action)
  }
  return state
}

// ------------------------ redux setup ------------------------

const { 
  createStore,
  applyMiddleware
  } = Redux

// apply logging middleware (not necessary)
// open the console to see the action logger output on each time new action dispatched
const actionLogger = ({ dispatch, getState }) => next => action => {
  console.log("action logger: action.type=%s state=%d", action.type, getState())
  return next(action)
}

// ------------------------ reducers ------------------------
// those will be creating new states and returning it,
// depending on the dispatched actions
addReducer(reducers, 'INCREMENT', (state, action) => ++state)
addReducer(reducers, 'DECREMENT', (state, action) => --state)

const DEFAULT_STATE = 0

const store = createStore(
  reducer, 
  DEFAULT_STATE, 
  applyMiddleware(actionLogger)
);

console.log(createStore)

// ------------------------ rendering ------------------------
let render = () => document.getElementById('counter-state').innerHTML = store.getState()

//
// IMPORTANT BINDING:
//
// store will be dispatching the new state to the render method each time the state changes
//
store.subscribe(render)

//
// render with the state for the first time
//
render()

// ------------------------ redux actions ------------------------

// continously increment the counter (the state) each second
setInterval(() => store.dispatch({type: 'INCREMENT'}), 1000)

// only increment the counter on click to the increase button
document
  .getElementById('increment-action')
  .addEventListener('click', () => store.dispatch({type: 'INCREMENT'}))

// only decrement the counter on click to the decrease button
document
  .getElementById('decrement-action')
  .addEventListener('click', () => store.dispatch({type: 'DECREMENT'}))