From 13a3a95574f0047abe0e3aa6e7c003c2f88e3b2b Mon Sep 17 00:00:00 2001 From: Kenny Date: Sat, 23 Apr 2016 15:23:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90Reducer=E5=AD=A6=E4=B9=A0?= =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 30 +++++++------- redux/reducer.md | 105 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 118 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 63990aa..31d0d69 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,34 @@ # React Native 学习旅程 ###本文档前置条件 -1. 已安装JDK,并配好环境变量。 -2. 已安装如下Android SDK,并配好环境变量。 +1. 已安装 JDK,并配好环境变量。 +2. 已安装如下 Android SDK,并配好环境变量。 - Android SDK Build-tools (23.0.1) - Android SDK Tools (24.3.3) - Android SDK Platform-tools (22) - Android 6.0 (API 23) - Android Support Library(23.0.1) -推荐从[AndroidDevTools](http://androiddevtools.cn/)下载或者用[腾讯Bugly](http://android-mirror.bugly.qq.com:8080/include/usage.html)镜像加速下载 +推荐从[AndroidDevTools](http://androiddevtools.cn/)下载或者用[腾讯Bugly](http://android-mirror.bugly.qq.com:8080/include/usage.html)镜像加速下载。 强烈建议配置为``` %ANDROID_HOME%; ``` ``` %ANDROID_HOME%\platform-tools; ``` ``` %ANDROID_HOME%\tools ```形式。 -### 安装C++环境 -- 下载并安装[Visual C++ 2013](https://www.microsoft.com/zh-cn/download/details.aspx?id=40784),选择vcredist_x64.exe(如果32位系统,下载vcredist_x86.exe),仅有**7M**大小,编译Node.js的C++模块时需要用到。 +### 安装 C++ 环境 +- 下载并安装[Visual C++ 2013](https://www.microsoft.com/zh-cn/download/details.aspx?id=40784),选择 vcredist_x64.exe(如果32位系统,下载 vcredist_x86.exe),仅有**7M**大小,编译 Node.js 的 C++ 模块时需要用到。 -### 安装Python -- 安装[Python 2.7.x](https://www.python.org/downloads/release/python-2711/)(3.x版本不行),安装时确保``` Add python.exe to Path ```已选中状态。 +### 安装 Python +- 安装[Python 2.7.x](https://www.python.org/downloads/release/python-2711/)(3.x版本不行),安装时确保 ``` Add python.exe to Path ``` 已选中状态。 -### 安装Node.js +### 安装 Node.js - 从官网下载[Node.js 4.4.x](https://nodejs.org/dist/v4.4.2/node-v4.4.2-x64.msi)的官方4.x版本,``` 不要安装5.x版本 ```,安装时确保``` Add to PATH ```已选中状态。 - 建议设置npm镜像以加速后面的过程(或使用科学上网工具)。
npm config set registry https://registry.npm.taobao.org
 npm config set disturl https://npm.taobao.org/dist
-### 安装Gradle +### 安装 Gradle - 虽然在编译Android项目时会自动下载,但如果网络状态不好,很容易下载失败,建议先下载[gradle-2.4-all.zip](http://pan.baidu.com/s/1c0dcgfe)。 -- 下载上述文件后,将zip文件放在``` C:\Users\kenny\\.gradle\wrapper\dists\gradle-2.4-all\6r4uqcc6ovnq6ac6s0txzcpc0 ``` (不存在的目录就手动创建)。 +- 下载上述文件后,将zip文件放在``` C:\Users\kenny\.gradle\wrapper\dists\gradle-2.4-all\6r4uqcc6ovnq6ac6s0txzcpc0 ``` (不存在的目录就手动创建)。 -### 安装react-native命令行工具 +### 安装 react-native 命令行工具
npm install -g react-native-cli
请耐心等待1-3分钟。 @@ -39,7 +39,7 @@ npm config set disturl https://npm.taobao.org/dist 请耐心等待5-10分钟。 -### 运行React Native +### 运行 React Native 进入RNProject目录, 在命令行里执行
react-native run-android
@@ -51,12 +51,12 @@ npm config set disturl https://npm.taobao.org/dist
adb reverse tcp:8081 tcp:8081
-建议使用Android 5.0系统手机,不用手动设置Debug server host,但是最低要求Android 4.1系统手机。 +建议使用 Android 5.0 系统手机,不用手动设置 Debug server host ,但是最低要求 Android 4.1 系统手机。 -提示:如果你执行``` adb devices ```没有问题,但执行上面``` adb reverse ```命令出问题,请下载 [utility/adb.zip](https://raw.githubusercontent.com/Kennytian/learning-react-native/master/utility/adb.zip) ,解压后,将3个文件放在``` %ANDROID_HOME%\platform-tools ```下 +提示:如果你执行``` adb devices ```没有问题,但执行上面``` adb reverse ```命令出问题,请下载 [utility/adb.zip](https://raw.githubusercontent.com/Kennytian/learning-react-native/master/utility/adb.zip) 关解压,将3个文件放在``` %ANDROID_HOME%\platform-tools ```下 ### 开发 -用IDE打开RNProject目录, 开始开发吧! +用 IDE 打开 RNProject 目录,开始开发吧! ### 反馈 - QQ:2225226 diff --git a/redux/reducer.md b/redux/reducer.md index 0f616c8..f7ee3bd 100644 --- a/redux/reducer.md +++ b/redux/reducer.md @@ -11,7 +11,8 @@ Action只描述了**有事情发生了**这一事实,而reducer要做的事就 通常,这个state树还需要存放其它一些UI数据,但尽量把这些数据与UI相关的state分开。 -
{
+

+{
   visibilityFilter: 'SHOW_ALL',
   hotels:[
   {
@@ -22,7 +23,8 @@ Action只描述了**有事情发生了**这一事实,而reducer要做的事就
     text: '客栈',
     isShow: false
   }]
-}
+} +
> ### 处理 Reducer 关系时的注意事项 > 开发复杂的应用时,不可避免会有一些数据相互引用。建议你尽可能地把 state 范式化,不存在嵌套。 @@ -30,6 +32,105 @@ Action只描述了**有事情发生了**这一事实,而reducer要做的事就 > 把应用的 state 想像成数据库。 > 例如,实际开发中,在 state 里同时存放 `hotelsById: { id -> hotel } 和 hotels: array` 是比较好的方式。 +## 处理单个 Action +reducer就是一个函数,接收旧的state和action,返回新的state. + +`(previousState,action) => newState` + +之所以称作reducer是因为它将被传递给`Array.prototype.reduce(reducer,?initialValue)`方法。保持reducer纯净是非常重要的,**永远不要在reducer里做这些操作**: +* 修改传入参数 +* 执行API请求和路由跳转等 +* 调用非纯属函数,如Date.now()等 + +只需要谨记reducer一定要保持纯净,**只要传入参数一样,返回必须一样。没有特殊情况,没有副作用,没有API请求、没有修改参数、单纯执行计算**。 + +

+function hotelApp(state = initialState, action) {
+    // 这里暂不处理任何 action,
+    // 仅返回传入的 state。
+    return state;
+}
+
+ +现在可以处理SET_VISIBILITY_FILTER, 需要做的只是改变state中的visibilityFilter. +

+function hotelApp(state = initialState, action) {
+    switch(action.type) {
+        case SET_VISIBILITY_FILTER:
+            return Object.assign({}, state, {
+                visibilityFilter: action.filter
+            });
+        default:
+            return state;
+    }
+}
+
+ +注意: +1. **不要修改state**, 使用 [Object.assign()](https://cnodejs.org/topic/56c49662db16d3343df34b13) 新建一个副本( `assign() 可以快速的复制一个或者多个对象到目标对象中` ). 不能`Object.assign(state, {visibilityFilter: action.filter})`, 因为它会改变第一个参数的值, **必须把第一个参数设置为空对象**, 即: `Object.assign({}, {visibilityFilter: action.filter})` +2. 在 default 情况下返回旧的 state. 遇到未知的 action时, 一定要返回旧的state. + +## 处理多个Action +还有两个action需要处理, 我们先处理`ADD_HOTEL`. +

+function hotelApp(state = initialState, action) {
+    switch(action.type) {
+        case SET_VISIBILITY_FILTER:
+            return Object.assign({}, state, {
+                visibilityFilter: action.filter,
+            });
+        case ADD_HOTEL:
+            return Object.assign({}, state, {
+                text: action.text,
+                isShow: false
+            });
+        default:
+            return state;
+    }
+}
+
+ +COMPLETE_TODO 也很好理解: +

+case COMPLETE_TODO:
+  return Object.assign({}, state, {
+    todos: [
+      ...state.todos.slice(0, action.index),          //比如: 0 ~ 5
+      Object.assign({}, state.todos[action.index], {  //此处为6
+        completed: true
+      }),
+      ...state.todos.slice(action.index + 1)          //后面就是7
+    ]
+  });
+
+我们不能直接修改却要更新数组中指定的一项数据,要先把**前面**和**后面**都切开。**时刻谨记永远不要在克隆 state 前修改它**。 + +combineReducers 接收一个对象, 可以把所有顶级的reducer 放到一个独立的文件中, 通过 export 暴露出每个 reducer 函数,然后使用 import * as reducer 得到一个以它们名字作为 key 的 object: +

+import { combineReducers } from 'redux';
+import * as reducers from './reducers';
+
+const hotelApp = combineReducers(reducers);
+
+ +### 知识补充: +

+var o1 = { a: 1 };
+var o2 = { b: 2 };
+var o3 = { c: 3 };
+
+var obj = Object.assign(o1, o2, o3);
+console.log(obj); // { a: 1, b: 2, c: 3 }
+console.log(o1);  // { a: 1, b: 2, c: 3 }, target object itself is changed.
+
+ +

+var str="Hello happy world!"
+str.slice(6); //happy world!
+
+var str="Hello happy world!"
+str.slice(6, 11) //happy
+
### 相关文档