Redux-example
Examples from http://redux.js.org/docs/introduction/Examples.html
Counter Vanilla
Run the Counter Vanilla example:
git clone https://github.com/reactjs/redux.git
cd redux/examples/counter-vanilla
open index.html
index.html
<!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>
分析:
function counter(state, action) {....}
作为一个函数,通过var store = Redux.createStore(counter)
变成了一个 store。
这个 store的两个参数可以通过store.getState()
和 store.dispatch({ type: 'INCREMENT' })
使用,返回值皆为 state。
store.subscribe(callbackFunc)
这个函数用于监听 state的变化,并调用 callbackFunc
.
其中 dispatch 函数还可以进行异步调用:
setTimeout(function () {
store.dispatch({ type: 'INCREMENT' }) }, 1000)
Counter
Run the Counter example:
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 )
Todos
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)
TodoMVC
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。它的作用主要是把字符串变成常量。