|
@@ -0,0 +1,134 @@
|
|
|
+# React and Redux
|
|
|
+
|
|
|
+> view层发出actions通知触发store里的reducer从而来更新state;state的改变会将更新反馈给我们的view层,从而让我们的view层发生相应的反应给用户。
|
|
|
+
|
|
|
+## 流程图
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+## 目录结构
|
|
|
+
|
|
|
+目录结构大概可以这样规划
|
|
|
+
|
|
|
+```
|
|
|
+app
|
|
|
+ |_components
|
|
|
+ |_reducers
|
|
|
+ |_actions
|
|
|
+ |_stores
|
|
|
+ |_configureStores.js
|
|
|
+ |_main.js
|
|
|
+```
|
|
|
+
|
|
|
+## 核心代码
|
|
|
+
|
|
|
+举例核心代码。值得注意的是其中有一个state的传递有一些迷惑的地方,在下面的注释中可以找到思路。
|
|
|
+
|
|
|
+### components
|
|
|
+```js
|
|
|
+import React, { Component } from 'react';
|
|
|
+import { bindActionCreators } from 'redux';
|
|
|
+import { connect } from 'react-redux';
|
|
|
+import * as CounterActions from '../../actions/counter.js';
|
|
|
+
|
|
|
+class Counter extends Component {
|
|
|
+ constructor() {
|
|
|
+ super();
|
|
|
+ this.state = {};
|
|
|
+ }
|
|
|
+ componentWillMount = () => {
|
|
|
+ this.startCount();
|
|
|
+ }
|
|
|
+ startCount = () => {
|
|
|
+ const { actions } = this.props;
|
|
|
+ actions.listen('INC');
|
|
|
+ }
|
|
|
+ render() {
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ {this.props.counter.count}
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+Counter.propTypes = {
|
|
|
+ actions: React.PropTypes.object.isRequired,
|
|
|
+ counter: React.PropTypes.object.isRequired
|
|
|
+};
|
|
|
+// 声明 connect 连接
|
|
|
+// 将 redux 中的 state传给 App
|
|
|
+function mapStateToProps(state) {
|
|
|
+ return {
|
|
|
+ counter: state.counter
|
|
|
+ };
|
|
|
+}
|
|
|
+function mapDispatchToProps(dispatch) {
|
|
|
+ const boundCounter = bindActionCreators(CounterActions, dispatch);
|
|
|
+ return {
|
|
|
+ actions: Object.assign({}, boundCounter)
|
|
|
+ };
|
|
|
+}
|
|
|
+// 声明 connect 连接
|
|
|
+export default connect(mapStateToProps, mapDispatchToProps)(Counter);
|
|
|
+```
|
|
|
+
|
|
|
+### actions
|
|
|
+
|
|
|
+action函数必须返回一个带有type属性的plain object。
|
|
|
+
|
|
|
+```js
|
|
|
+import * as constants from '../../constants/counter';
|
|
|
+export function listen(type) {
|
|
|
+ switch (type) {
|
|
|
+ case 'INC':
|
|
|
+ return {
|
|
|
+ type: constants.INC
|
|
|
+ };
|
|
|
+ case 'DEC':
|
|
|
+ return {
|
|
|
+ type: constants.DEC
|
|
|
+ };
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### reducers
|
|
|
+
|
|
|
+reducer就是迎接action函数返回的线索的数据再处理函数,action是预处理函数。
|
|
|
+
|
|
|
+```js
|
|
|
+import {INC, DEC} from '../../constants/counter';
|
|
|
+// 初始状态
|
|
|
+const initState = {
|
|
|
+ count: 1
|
|
|
+};
|
|
|
+// 定义转换的reducer函数
|
|
|
+// action = {type: 'INC',counter: {count: 1}};
|
|
|
+export default function start(state = initState, action) {
|
|
|
+ switch (action.type) {
|
|
|
+ case INC:
|
|
|
+ // 对这个action做出响应
|
|
|
+ state.count += 1 ; // 改变状态
|
|
|
+ // return {count: 2} 返回给页面;
|
|
|
+ return state;
|
|
|
+ case DEC:
|
|
|
+ // 对这个action做出响应
|
|
|
+ state.count -= 1; // 改变状态
|
|
|
+ // return {count: 0} 返回给页面;
|
|
|
+ return state
|
|
|
+ default:
|
|
|
+ return state;
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+```js
|
|
|
+import { combineReducers } from 'redux';
|
|
|
+import counter from './counter'; // {count: 2}返回给页面,所以页面用的是counter.count获取数据2
|
|
|
+// 通过combineReducers将多个reducer合并成一个rootReducer:
|
|
|
+const rootReducer = combineReducers({
|
|
|
+ counter, // {count: 1}
|
|
|
+ others
|
|
|
+});
|
|
|
+export default rootReducer;
|
|
|
+```
|