Examples from http://redux.js.org/docs/introduction/Examples.htmlhtml
Run the Counter Vanilla example:node
git clone https://github.com/reactjs/redux.git cd redux/examples/counter-vanilla open index.html
index.htmlreact
<!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>
分析:git
function counter(state, action) {....}
做爲一個函數,經過var store = Redux.createStore(counter)
變成了一個 store。github
這個 store的兩個參數能夠經過store.getState()
和 store.dispatch({ type: 'INCREMENT' })
使用,返回值皆爲 state。npm
store.subscribe(callbackFunc)
這個函數用於監聽 state的變化,並調用 callbackFunc
.redux
其中 dispatch 函數還能夠進行異步調用:mvc
setTimeout(function () { store.dispatch({ type: 'INCREMENT' }) }, 1000)
Run the Counter example:dom
git clone https://github.com/reactjs/redux.git cd redux/examples/counter npm install npm start open http://localhost:3000/
項目結構異步
reducers 中 store 函數
export default (state = 0, action) => { switch (action.type) { case 'INCREMENT': return state + 1 case 'DECREMENT': return state - 1 default: return state } }
index.js 中經過 prop傳遞 store
const render = () => ReactDOM.render( <Counter value={store.getState()} onIncrement={() => store.dispatch({ type: 'INCREMENT' })} onDecrement={() => store.dispatch({ type: 'DECREMENT' })} />, rootEl )
Run the Todos example:
git clone https://github.com/reactjs/redux.git cd redux/examples/todos npm install npm start open http://localhost:3000/
項目結構
這個例子中 store 再也不是一個組件組成,而是由多個組件混合。而且 store中對 action的操做再也不僅僅是判斷 action.type,還能夠獲取更多的 action屬性。
使用 react-redux
的 Provider 建立一個帶有 store的容器
import { createStore } from 'redux' import { Provider } from 'react-redux' import reducer from './reducers' const store = createStore(reducer) render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') )
而 App 組件是由3個組件構成
const App = () => ( <div> <AddTodo /> <VisibleTodoList /> <Footer /> </div> )
其中一個組件,調用 dispatch 傳遞 action函數做爲參數。
而經過react-redux
的 connect 組件將其關聯到 store上。
import { connect } from 'react-redux' import { addTodo } from '../actions' let AddTodo = ({ dispatch }) => { let input return ( <div> <form onSubmit={e => { e.preventDefault() if (!input.value.trim()) { return } dispatch(addTodo(input.value)) input.value = '' }}> <input ref={node => { input = node }} /> <button type="submit"> Add Todo </button> </form> </div> ) } AddTodo = connect()(AddTodo)
Run the TodoMVC example:
git clone https://github.com/reactjs/redux.git cd redux/examples/todomvc npm install npm start open http://localhost:3000/
項目結構
這個項目跟上個項目並沒有大體,只不過多了一個 constants。它的做用主要是把字符串變成常量。