🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
Redux 的设计思想很简单,就两句话。 1. Web 应用是一个状态机,视图与状态是一一对应的。 2. 所有的状态,保存在一个对象里面。 redux工作流程图 ![](https://box.kancloud.cn/4f09784d4ccbf60fb8e8f4b7f643841b_638x479.jpg) API文档:http://www.redux.org.cn/ ## 一、简单示例 效果: ![](https://box.kancloud.cn/ce8d1c818c7ab7c28fc72b2b93b8c168_416x38.jpg) index.js ~~~ import React from 'react' import ReactDOM from 'react-dom' import { createStore } from 'redux' import Counter from './components/Counter' import counter from './reducers' const store = createStore(counter) const rootEl = document.getElementById('root') const render = () => ReactDOM.render( <Counter value={store.getState()} onIncrement={() => store.dispatch({ type: 'INCREMENT' })} onDecrement={() => store.dispatch({ type: 'DECREMENT' })} />, rootEl ) render() store.subscribe(render) ~~~ reducers/index.js ~~~ export default (state = 0, action) => { switch (action.type) { case 'INCREMENT': return state + 1 case 'DECREMENT': return state - 1 default: return state } } ~~~ components/Counter.js ~~~ import React, { Component } from 'react' import PropTypes from 'prop-types' class Counter extends Component { constructor(props) { super(props); this.incrementAsync = this.incrementAsync.bind(this); this.incrementIfOdd = this.incrementIfOdd.bind(this); } incrementIfOdd() { if (this.props.value % 2 !== 0) { this.props.onIncrement() } } incrementAsync() { setTimeout(this.props.onIncrement, 1000) } render() { const { value, onIncrement, onDecrement } = this.props return ( <p> Clicked: {value} times {' '} <button onClick={onIncrement}> + </button> {' '} <button onClick={onDecrement}> - </button> {' '} <button onClick={this.incrementIfOdd}> Increment if odd </button> {' '} <button onClick={this.incrementAsync}> Increment async </button> </p> ) } } Counter.propTypes = { value: PropTypes.number.isRequired, onIncrement: PropTypes.func.isRequired, onDecrement: PropTypes.func.isRequired } export default Counter ~~~ 上面代码简化合并 ~~~ import React, { Component } from 'react' import ReactDOM from 'react-dom' import { createStore } from 'redux' import PropTypes from 'prop-types' class Counter extends Component { constructor(props) { super(props); this.incrementAsync = this.incrementAsync.bind(this); this.incrementIfOdd = this.incrementIfOdd.bind(this); this.propTypes = { value: PropTypes.number.isRequired, onIncrement: PropTypes.func.isRequired, onDecrement: PropTypes.func.isRequired }; } incrementIfOdd() { if (this.props.value % 2 !== 0) { this.props.onIncrement() } } incrementAsync() { setTimeout(this.props.onIncrement, 1000) } render() { const { value, onIncrement, onDecrement } = this.props return ( <p> Clicked: {value} times {' '} <button onClick={onIncrement}> + </button> {' '} <button onClick={onDecrement}> - </button> {' '} <button onClick={this.incrementIfOdd}> Increment if odd </button> {' '} <button onClick={this.incrementAsync}> Increment async </button> </p> ) } } const store = createStore((state = 0, action) => { switch (action.type) { case 'INCREMENT': return state + 1 case 'DECREMENT': return state - 1 default: return state } }); const render = () => ReactDOM.render( <Counter value={store.getState()} onIncrement={() => store.dispatch({ type: 'INCREMENT' })} onDecrement={() => store.dispatch({ type: 'DECREMENT' })} />, document.getElementById('root') ) render(); store.subscribe(render); ~~~ ## 二、redux、react-redux、react-router配合使用 ![](https://box.kancloud.cn/aecfdffff1c9fea3f2bd5097ff37663f_120x40.gif) 入口文件 index.js ~~~ import React from 'react'; import ReactDOM from 'react-dom'; import {Router, browserHistory} from 'react-router'; import {Provider} from "react-redux"; import store from './redux'; import routes from './routes'; import registerServiceWorker from './registerServiceWorker'; ReactDOM.render(<Provider store={store}><Router history={browserHistory}>{routes}</Router></Provider>, document.getElementById('root')); registerServiceWorker(); // 用于生产环境cache数据 ~~~ 路由 routes/index.js ~~~ import App from '../App'; const routes = [ { path: '/', component: App } ]; export default routes; ~~~ redux/index.js ~~~ import { createStore } from 'redux'; function toDo(state={name: 'tom'}, action) { if(!state) state={name: 'tom'}; switch (action.type) { case 'CHANGE_NAME': return {...state, ...action.payload}; default: return state; } } let store = createStore(toDo); export default store; ~~~ 组件 App.js ~~~ import React, { Component } from 'react'; import {connect} from "react-redux"; class App extends Component { constructor(props){ super(props); } render() { return ( <div> {this.props.cName} <button type="button" onClick={this.changeName.bind(this)}>改变name</button> </div> ); } changeName() { this.props.changeName({name: 'jack'}); } } function mapStateToProps(state, props) { return { cName: state.name } } function mapDispatchToProps(dispatch, props) { return { changeName: (payload)=>dispatch({type: 'CHANGE_NAME', payload: payload}) } } export default connect(mapStateToProps, mapDispatchToProps)(App); ~~~ 参考链接:http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html