├── README.md └── Tutorial ├── 01 React入门.md ├── 02【阮一峰】React 入门实例教程.md ├── 03 Webpack.md ├── 04 React Router.md ├── 05【阮一峰】Babel 入门教程.md ├── 06【阮一峰】webpack-demos.md ├── 07【阮一峰】Redux 入门教程(一):基本用法.md ├── 08【阮一峰】Redux 入门教程(二):中间件与异步操作.md ├── 09【阮一峰】Redux 入门教程(三):React-Redux 的用法.md ├── 10 Redux 简明教程.md ├── 11【慕课网】在React中使用Redux数据流.md ├── 12 redux-tutorial.md ├── 13【Redux 中文文档】1.介绍.md ├── 14【Redux 中文文档】2. 基础.md ├── 15【Redux 中文文档】3. 高级.md ├── 16【Redux 中文文档】4. 技巧.md ├── 17【Redux 中文文档】5. 常见问题.md └── README.md /README.md: -------------------------------------------------------------------------------- 1 | # ReactCollect 2 | 收集整理React相关 3 | 4 | 5 | ## React文档教程 6 | | 教程 | 说明 | 评价 | 7 | | ------------ | ------------ | ------------ | 8 | |[官网文档](https://facebook.github.io/react/docs/hello-world.html)|官方文档要看一遍,非常重要,即使是英文 | ✔✔✔✔✔ | 9 | |[React Gitbook 翻译](https://hulufei.gitbooks.io/react-tutorial/content/introduction.html)|很好react中文文档|✔✔✔✔| 10 | |[awesome-react](https://github.com/enaqx/awesome-react)|awesome react系列,英文资源|✔✔✔✔| 11 | |[React 入门实例教程](http://www.ruanyifeng.com/blog/2015/03/react.html)|【阮一峰】react的入门教程,配有demo|✔✔✔✔| 12 | |[React Router 使用教程](http://www.ruanyifeng.com/blog/2016/05/react_router.html?utm_source=tool.lu)|【阮一峰】react-router教程|✔✔✔| 13 | |[React 技术栈系列教程](http://www.ruanyifeng.com/blog/2016/09/react-technology-stack.html)|【阮一峰】react全家桶介绍|✔✔✔✔| 14 | |[React Router Tutorial](https://github.com/reactjs/react-router-tutorial)|官方的react-router教程,配有demo,必看|✔✔✔✔✔| 15 | 16 | 17 | ## React视频教程 18 | | 教程 | 说明 | 评价 | 19 | | ------------ | ------------ | ------------ | 20 | |[React入门](http://www.imooc.com/learn/504)|React实践图片画廊教程的前置教程|✔✔✔| 21 | |[React实战--打造画廊应用(上)](http://www.imooc.com/learn/507)|用react打造一个图片画廊应用|✔✔✔| 22 | |[React实践图片画廊应用(下)](http://www.imooc.com/learn/652)|用react打造一个图片画廊应用(下)|✔✔✔| 23 | 24 | ## Redux文档教程 25 | | 教程 | 说明 | 评价 | 26 | | ------------ | ------------ | ------------ | 27 | |[Redux 官方文档](http://redux.js.org/)|Redux官方文档 | ✔✔✔✔✔ | 28 | |[Redux 中文文档](http://cn.redux.js.org/index.html)|Redux官方文档的中文翻译 | ✔✔✔✔✔ | 29 | |[redux-tutorial中文翻译](https://github.com/react-guide/redux-tutorial-cn#redux-tutorial)| 一个简短的redux教程 | ✔✔✔ | 30 | |[Redux 入门教程](http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html)| 【阮一峰】redux教程,有3篇| ✔✔✔ | 31 | |[Redux 简明教程](https://github.com/kenberkeley/redux-simple-tutorial)|redux莞式教程,很好的教程 | ✔✔✔✔ | 32 | 33 | ## MobX文档教程 34 | | 教程 | 说明 | 评价 | 35 | | ------------ | ------------ | ------------ | 36 | |[MobX 官方文档](https://mobx.js.org/best/decorators.html)|MobX官方文档 | ✔✔✔✔ | 37 | |[MobX 中文文档](https://gismanli.gitbooks.io/mobx-zh/)|MobX官方文档的中文翻译 | ✔✔✔✔ | 38 | -------------------------------------------------------------------------------- /Tutorial/01 React入门.md: -------------------------------------------------------------------------------- 1 | ### React入门 2 | [教程地址:React入门](http://www.imooc.com/learn/504) 3 | 4 | --- 5 | ### 第1章 课程介绍 6 | #### 1-1 React入门课程介绍 7 | - 初识React 8 | - React不是一个完整的MVC,MVVM框架 9 | - React和Web Components不冲突 10 | - React的特点就是轻 11 | - 组件化的开发思路 12 | 13 | - React应用场景 14 | - 复杂场景下的高性能 15 | - 重用组件库,组件组合 16 | - 懒 17 | 18 | ---- 19 | ### 第2章 React的JSX与Style 20 | #### 2-1 React-JSX-Style 21 | - 进react官网然后再jsfiddle里学习react 22 | - react 中的关键字 class => calssName 23 | - react 中style的写法,style={(匿名)对象} 24 | - react 中的所有标签都是web component 对象 25 | 26 | ### 第3章 React组件的生命周期和事件处理 27 | #### 3-1 React-Components-Lifecycle 28 | - 三个生命周期 29 | - hook函数 30 | - this指针 31 | 32 | #### 3-2 React-Event-Listener 33 | - react中的onClick和原生js的onclick不是一回事 34 | 35 | -------------------------------------------------------------------------------- /Tutorial/02【阮一峰】React 入门实例教程.md: -------------------------------------------------------------------------------- 1 | ### # React 入门实例教程 2 | [教程地址:React 入门实例教程](http://www.ruanyifeng.com/blog/2015/03/react.html) 3 | 4 | --- 5 | ### 1. HTML 模板 6 | - 凡是使用 JSX 的地方,都要加上 `type="text/babel"` 7 | 8 | --- 9 | ### 2. ReactDOM.render() 10 | - ReactDOM.render 是 React 的最基本方法,用于将模板转为 HTML 语言,并插入指定的 DOM 节点 11 | 12 | --- 13 | ### 3. JSX 语法 14 | - HTML 语言直接写在 JavaScript 语言之中,不加任何引号,这就是**JSX** 的语法,它允许 HTML 与 JavaScript 的混写 15 | - JSX 的基本语法规则:遇到 HTML 标签(以 `<` 开头),就用 HTML 规则解析;遇到代码块(以 `{` 开头),就用 JavaScript 规则解析 16 | - JSX 允许直接在模板插入 JavaScript 变量。如果这个变量是一个数组,则会展开这个数组的所有成员 17 | 18 | --- 19 | ### 4. 组件 20 | - React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。React.createClass 方法就用于生成一个组件类 21 | - 注意,组件类的第一个字母必须大写,否则会报错,比如`HelloMessage`不能写成`helloMessage`。另外,组件类只能包含一个顶层标签,否则也会报错 22 | - 组件的用法与原生的 HTML 标签完全一致,可以任意加入属性,比如 `` ,就是 `HelloMessage` 组件加入一个 `name` 属性,值为 `John` 23 | - 组件的属性可以在组件类的 `this.props` 对象上获取,比如 `name` 属性就可以通过 `this.props.name` 读取 24 | - 添加组件属性,有一个地方需要注意,就是 `class` 属性需要写成 `className` ,`for` 属性需要写成 `htmlFor` ,这是因为 `class` 和 `for` 是 JavaScript 的保留字 25 | 26 | --- 27 | ### 5. this.props.children 28 | - `this.props` 对象的属性与组件的属性一一对应,但是有一个例外,就是 `this.props.children` 属性。它表示组件的所有子节点 29 | 30 | --- 31 | ### 6. PropTypes 32 | - 组件的属性可以接受任意值,字符串、对象、函数等等都可以。有时,我们需要一种机制,验证别人使用组件时,提供的参数是否符合要求 33 | - 组件类的`PropTypes`属性,就是用来验证组件实例的属性是否符合要求 34 | - 此外,`getDefaultProps` 方法可以用来设置组件属性的默认值 35 | 36 | --- 37 | ### 7. 获取真实的DOM节点 38 | - 组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,这种算法叫做 **DOM diff**,它可以极大提高网页的性能表现 39 | - 但是,有时需要从组件获取真实 DOM 的节点,这时就要用到 `ref` 属性 40 | - 需要注意的是,由于 `this.refs.[refName]` 属性获取的是真实 DOM ,所以必须等到虚拟 DOM 插入文档以后,才能使用这个属性,否则会报错 41 | 42 | --- 43 | ### 8. this.state 44 | - 组件免不了要与用户互动,React 的一大创新,就是将组件看成是一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染 UI 45 | - `getInitialState` 方法用于定义初始状态,也就是一个对象,这个对象可以通过 `this.state` 属性读取。当用户点击组件,导致状态变化,`this.setState` 方法就修改状态值,每次修改以后,自动调用 `this.render` 方法,再次渲染组件 46 | - 由于 `this.props` 和 `this.state` 都用于描述组件的特性,可能会产生混淆。一个简单的区分方法是,`this.props` 表示那些一旦定义,就不再改变的特性,而 `this.state` 是会随着用户互动而产生变化的特性 47 | 48 | --- 49 | ### 9. 表单 50 | - 用户在表单填入的内容,属于用户跟组件的互动,所以不能用 `this.props` 读取 51 | 52 | --- 53 | ### 10. 组件的生命周期 54 | - 组件的生命周期分成三个状态 55 | * Mounting:已插入真实 DOM 56 | * Updating:正在被重新渲染 57 | * Unmounting:已移出真实 DOM 58 | 59 | - React 为每个状态都提供了两种处理函数,`will` 函数在进入状态之前调用,`did` 函数在进入状态之后调用,三种状态共计五种处理函数 60 | * componentWillMount() 61 | * componentDidMount() 62 | * componentWillUpdate(object nextProps, object nextState) 63 | * componentDidUpdate(object prevProps, object prevState) 64 | * componentWillUnmount() 65 | 66 | - 此外,React 还提供两种特殊状态的处理函数 67 | * componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用 68 | * shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用 69 | 70 | - [React 组件样式](https://facebook.github.io/react/tips/inline-styles.html)是一个对象,所以第一重大括号表示这是 JavaScript 语法,第二重大括号表示样式对象 71 | 72 | --- 73 | ### 11. Ajax 74 | - 组件的数据来源,通常是通过 Ajax 请求从服务器获取,可以使用 `componentDidMount` 方法设置 Ajax 请求,等到请求成功,再用 `this.setState` 方法重新渲染 UI 75 | -------------------------------------------------------------------------------- /Tutorial/03 Webpack.md: -------------------------------------------------------------------------------- 1 | ### webpack 2 | [如何使用webpack—webpack-howto](http://www.tuicool.com/articles/rQFZFvU) 3 | [阮一峰:webpack demos(英文)](https://github.com/ruanyf/webpack-demos) 4 | [阮一峰webpakc教程的翻译](http://www.cnblogs.com/worldly1013/p/5989863.html) 5 | [WebPack 简明学习教程](http://www.jianshu.com/p/b95bbcfc590d) 6 | [webpack-dev-server说明](http://www.jianshu.com/p/941bfaf13be1) 7 | [WebPack常用功能介绍](http://www.tuicool.com/articles/vAbYruq) 8 | [(三)webpack入门——webpack功能集合的demo](http://www.cnblogs.com/erduyang/p/5617917.html) 9 | [WebPack 常用功能介绍](https://segmentfault.com/a/1190000004172052) 10 | 11 | 12 | --- 13 | ### 1. webpack-dev-server 14 | - webpack-dev-server是一个小型的node.js Express服务器,它使用webpack-dev-middleware中间件来为通过webpack打包生成的资源文件提供Web服务 15 | - 简单来说,webpack-dev-server就是一个小型的静态文件服务器。使用它,可以为webpack打包生成的资源文件提供Web服务 16 | - webpack-dev-server有两种模式支持自动刷新——iframe模式和inline模式。在iframe模式下:页面是嵌套在一个iframe下的,在代码发生改动的时候,这个iframe会重新加载;在inline模式下:一个小型的webpack-dev-server客户端会作为入口文件打包,这个客户端会在后端代码改变的时候刷新页面 17 | 18 | ``` 19 | webpack-dev-server 20 | webpack-dev-server就是一个小型的静态文件服务器。使用它,可以为webpack打包生成的资源文件提供Web服务 21 | ``` 22 | 23 | 24 | --- 25 | ### 2. 一个 webpack.config.js案例 26 | ``` 27 | ``` 28 | var webpack = require('webpack'); 29 | var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js'); 30 | module.exports = { 31 | //插件项 32 | plugins: [commonsPlugin], 33 | //页面入口文件配置 34 | entry: { 35 | index : './src/js/page/index.js' 36 | }, 37 | //入口文件输出配置 38 | output: { 39 | path: 'dist/js/page', 40 | filename: '[name].js' 41 | }, 42 | module: { 43 | //加载器配置 44 | loaders: [ 45 | { test: /\.css$/, loader: 'style-loader!css-loader' }, 46 | { test: /\.js$/, loader: 'jsx-loader?harmony' }, 47 | { test: /\.scss$/, loader: 'style!css!sass?sourceMap'}, 48 | { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'} 49 | ] 50 | }, 51 | //其它解决方案配置 52 | resolve: { 53 | root: 'E:/github/flux-example/src', //绝对路径 54 | extensions: ['', '.js', '.json', '.scss'], 55 | alias: { 56 | AppStore : 'js/stores/AppStores.js', 57 | ActionType : 'js/actions/ActionType.js', 58 | AppAction : 'js/actions/AppAction.js' 59 | } 60 | } 61 | }; 62 | ``` 63 | ``` 64 | -------------------------------------------------------------------------------- /Tutorial/04 React Router.md: -------------------------------------------------------------------------------- 1 | ### React Router 2 | [教程地址:React Router](http://www.ruanyifeng.com/blog/2016/05/react_router.html?utm_source=tool.lu) 3 | 4 | --- 5 | 6 | 7 | -------------------------------------------------------------------------------- /Tutorial/05【阮一峰】Babel 入门教程.md: -------------------------------------------------------------------------------- 1 | ### Babel 入门教程 2 | [教程地址:Babel 入门教程](http://www.ruanyifeng.com/blog/2016/01/babel.html) 3 | 4 | --- 5 | - Babel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行,这意味着,你可以现在就用ES6编写程序,而不用担心现有环境是否支持 6 | 7 | --- 8 | ### 一、配置文件.babelrc 9 | - Babel的配置文件是`.babelrc`,存放在项目的根目录下。使用Babel的第一步,就是配置这个文件 10 | - 该文件用来设置转码规则和插件,基本格式如下 11 | 12 | ``` 13 | { 14 | "presets": [], 15 | "plugins": [] 16 | } 17 | ``` 18 | 19 | - presets字段设定转码规则,官方的规则集,可以根据需要安装。 20 | 21 | ``` 22 | # ES2015转码规则 23 | $ npm install --save-dev babel-preset-es2015 24 | 25 | # react转码规则 26 | $ npm install --save-dev babel-preset-react 27 | 28 | # ES7不同阶段语法提案的转码规则(共有4个阶段),选装一个 29 | $ npm install --save-dev babel-preset-stage-0 30 | $ npm install --save-dev babel-preset-stage-1 31 | $ npm install --save-dev babel-preset-stage-2 32 | $ npm install --save-dev babel-preset-stage-3 33 | ``` 34 | 35 | - 然后,将这些规则加入.babelrc 36 | 37 | ``` 38 | { 39 | "presets": [ 40 | "es2015", 41 | "react", 42 | "stage-2" 43 | ], 44 | "plugins": [] 45 | } 46 | ``` 47 | 48 | --- 49 | ### 二、命令行转码babel-cli 50 | - Babel提供babel-cli工具,用于命令行转码 51 | - 基本用法如下 52 | 53 | ``` 54 | # 转码结果输出到标准输出 55 | $ babel example.js 56 | 57 | # 转码结果写入一个文件 58 | # --out-file 或 -o 参数指定输出文件 59 | $ babel example.js --out-file compiled.js 60 | # 或者 61 | $ babel example.js -o compiled.js 62 | 63 | # 整个目录转码 64 | # --out-dir 或 -d 参数指定输出目录 65 | $ babel src --out-dir lib 66 | # 或者 67 | $ babel src -d lib 68 | 69 | # -s 参数生成source map文件 70 | $ babel src -d lib -s 71 | ``` 72 | 73 | --- 74 | ### 三、babel-node 75 | - `babel-cli`工具自带一个`babel-node`命令,提供一个支持ES6的REPL环境。它支持Node的REPL环境的所有功能,而且可以直接运行ES6代码 76 | - 它不用单独安装,而是随`babel-cli`一起安装。然后,执行`babel-node`就进入PEPL环境 77 | - `babel-node`命令可以直接运行ES6脚本 78 | 79 | 80 | --- 81 | ### 四、babel-register 82 | - `babel-register`模块改写`require`命令,为它加上一个钩子。此后,每当使用`require`加载`.js`、`.jsx`、`.es`和`.es6`后缀名的文件,就会先用Babel进行转码 83 | - 需要注意的是,`babel-register`只会对`require`命令加载的文件转码,而不会对当前文件转码。另外,由于它是实时转码,所以只适合在开发环境使用 84 | 85 | --- 86 | ### 五、babel-core 87 | - 如果某些代码需要调用Babel的API进行转码,就要使用`babel-core`模块 88 | 89 | --- 90 | ### 六、babel-polyfill 91 | - Babel默认只转换新的JavaScript句法(syntax),而不转换新的API,比如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局对象,以及一些定义在全局对象上的方法(比如`Object.assign`)都不会转码 92 | - 举例来说,ES6在`Array`对象上新增了`Array.from`方法。Babel就不会转码这个方法。如果想让这个方法运行,必须使用`babel-polyfill`,为当前环境提供一个垫片 93 | 94 | ``` 95 | npm install --save babel-polyfill 96 | 97 | //然后,在脚本头部,加入如下一行代码 98 | import 'babel-polyfill'; 99 | // 或者 100 | require('babel-polyfill'); 101 | ``` 102 | 103 | --- 104 | ### 七、浏览器环境 105 | - Babel也可以用于浏览器环境。但是,从Babel 6.0开始,不再直接提供浏览器版本,而是要用构建工具构建出来。如果你没有或不想使用构建工具,可以通过安装5.x版本的babel-core模块获取 106 | - browser.js是Babel提供的转换器脚本,可以在浏览器运行。用户的ES6脚本放在script标签之中,但是要注明type="text/babel" 107 | 108 | 109 | --- 110 | ### 八、在线转换 111 | - Babel提供一个REPL在线编译器,可以在线将ES6代码转为ES5代码。转换后的代码,可以直接作为ES5代码插入网页运行 112 | 113 | --- 114 | ### 九、与其他工具的配合 115 | - 许多工具需要Babel进行前置转码,这里举两个例子:ESLint和Mocha 116 | -------------------------------------------------------------------------------- /Tutorial/06【阮一峰】webpack-demos.md: -------------------------------------------------------------------------------- 1 | ### webpack-demos 2 | [教程地址:webpack-demos](https://github.com/ruanyf/webpack-demos#demo01-entry-file-source) 3 | 4 | --- 5 | 6 | webpack 基础命令 7 | ``` 8 | webpack for building once for development 9 | webpack -p 压缩混淆脚本 10 | webpack --watch 监听变动并自动打包 11 | webpack -d 生成map映射文件,告知哪些模块被最终打包到哪里了 12 | webpack --colors for making things pretty 13 | ``` 14 | 15 | ### 1. 入口文件 16 | ```js 17 | /* webpack.config.js */ 18 | module.exports = { 19 | entry: './main.js', 20 | output: { 21 | filename: 'bundle.js' 22 | } 23 | }; 24 | ``` 25 | >entry: 打包的入口文件(wepack不会处理index.html) 26 | >output.filename: 打包后的文件名字 27 | 28 | --- 29 | ### 2. 多入口文件 30 | ``` 31 | /* webpack.config.js */ 32 | module.exports = { 33 | entry: { 34 | bundle1: './main1.js', 35 | bundle2: './main2.js' 36 | }, 37 | output: { 38 | filename: '[name].js' 39 | } 40 | }; 41 | ``` 42 | >最终将main1.js以及这个文件require的其他文件打包成bundle1.js 43 | >将main2.js以及这个文件require的其他文件打包成bundle2.js 44 | 45 | --- 46 | ### 3. Babel-loader 47 | ``` 48 | /* webpack.config.js */ 49 | module.exports = { 50 | entry: './main.jsx', 51 | output: { 52 | filename: 'bundle.js' 53 | }, 54 | module: { 55 | loaders:[ 56 | { 57 | test: /\.js[x]?$/, 58 | exclude: /node_modules/, 59 | loader: 'babel-loader?presets[]=es2015&presets[]=react' 60 | }, 61 | ] 62 | } 63 | }; 64 | ``` 65 | >babel-loader能够将JSX/ES6语法转化为ES5 66 | >这里babel-loader还需要两个插件babel-preset-es2015 和 babel-preset-react 67 | 68 | 69 | --- 70 | ### 4. CSS-loader 71 | ``` 72 | /* webpack.config.js */ 73 | module.exports = { 74 | entry: './main.js', 75 | output: { 76 | filename: 'bundle.js' 77 | }, 78 | module: { 79 | loaders:[ 80 | { test: /\.css$/, loader: 'style-loader!css-loader' }, 81 | ] 82 | } 83 | }; 84 | ``` 85 | >css-loader用于在js文件中require一个css文件,读取css文件 86 | >style-loader用于将css样式插入到页面中 87 | >两个loader都要,而且执行顺序是由后至前,先css-loader再style-loader 88 | 89 | --- 90 | ### 5. Image loader 91 | ``` 92 | module.exports = { 93 | entry: './main.js', 94 | output: { 95 | filename: 'bundle.js' 96 | }, 97 | module: { 98 | loaders:[ 99 | { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192' } 100 | ] 101 | } 102 | }; 103 | ``` 104 | >url-loader: 这里配置limit=8192意思是如果图片小于8kb则转化为data url 105 | 106 | --- 107 | ### 6. CSS Module 108 | ``` 109 | module.exports = { 110 | entry: './main.jsx', 111 | output: { 112 | filename: 'bundle.js' 113 | }, 114 | module: { 115 | loaders:[ 116 | { 117 | test: /\.js[x]?$/, 118 | exclude: /node_modules/, 119 | loader: 'babel-loader', 120 | query: { 121 | presets: ['es2015', 'react'] 122 | } 123 | }, 124 | { 125 | test: /\.css$/, 126 | loader: 'style-loader!css-loader?modules' 127 | } 128 | ] 129 | } 130 | }; 131 | ``` 132 | >用于css的模块化,是css也有作用域 133 | 134 | --- 135 | ### 7. UglifyJs Plugin 136 | ``` 137 | ar webpack = require('webpack'); 138 | var uglifyJsPlugin = webpack.optimize.UglifyJsPlugin; 139 | module.exports = { 140 | entry: './main.js', 141 | output: { 142 | filename: 'bundle.js' 143 | }, 144 | plugins: [ 145 | new uglifyJsPlugin({ 146 | compress: { 147 | warnings: false 148 | } 149 | }) 150 | ] 151 | }; 152 | ``` 153 | >用于代码的混淆压缩 154 | 155 | --- 156 | ### 8. HTML Webpack Plugin and Open Browser Webpack Plugin 157 | >html-webpack-plugin能生成一个html文件 158 | >open-browser-webpack-plugin能够自动打开浏览器 159 | 160 | --- 161 | ### 9. Environment flags 162 | >设置一些环境变量,这样方便开发环境调试 163 | 164 | --- 165 | ### 10. Code splitting 166 | >使用require.ensure 实现代码分割,按需加载 167 | 168 | --- 169 | ### 11. Code splitting with bundle-loader 170 | >使用 bundle-loader来进行代码分割按需加载‘ 171 | 172 | --- 173 | ### 12. Common chunk 174 | >抽出公共模块 175 | 176 | --- 177 | ### 13. Vendor chunk 178 | >将公共库抽离出来,不要打成一个包,比如jquery 179 | 180 | --- 181 | ### 14. Exposing global variables 182 | >定义一个全局变量,在webpack.config.js中配置,然后使用的使用当作一个模块引入,这时候这个变量实际是全局变量了(有异议,仔细看例子) 183 | 184 | ``` 185 | // webpack.config.js 186 | module.exports = { 187 | entry: './main.jsx', 188 | output: { 189 | filename: 'bundle.js' 190 | }, 191 | module: { 192 | loaders:[ 193 | { 194 | test: /\.js[x]?$/, 195 | exclude: /node_modules/, 196 | loader: 'babel-loader', 197 | query: { 198 | presets: ['es2015', 'react'] 199 | } 200 | }, 201 | ] 202 | }, 203 | externals: { 204 | // require('data') is external and available 205 | // on the global var data 206 | 'data': 'data' 207 | } 208 | }; 209 | 210 | 211 | // main.jsx 212 | var data = require('data'); 213 | var React = require('react'); 214 | var ReactDOM = require('react-dom'); 215 | 216 | ReactDOM.render( 217 |

{data}

, 218 | document.body 219 | ); 220 | ``` 221 | 222 | --- 223 | ### 15. Hot Module Replacement 224 | - 两种方式 225 | 226 | ``` 227 | 第一种 228 | webpack-dev-server --hot --inline 229 | 230 | 第二种 231 | entry: [ 232 | 'webpack/hot/dev-server', 233 | 'webpack-dev-server/client?http://localhost:8080', 234 | './index.js' 235 | ], 236 | ``` 237 | >自己尝试两种本地都无法热更新 238 | 239 | 240 | --- 241 | ### 16. React router 242 | >一个react router的例子 243 | -------------------------------------------------------------------------------- /Tutorial/07【阮一峰】Redux 入门教程(一):基本用法.md: -------------------------------------------------------------------------------- 1 | ### Redux 入门教程(一):基本用法 2 | [教程地址;Redux 入门教程(一):基本用法](http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html) 3 | 4 | --- 5 | ### 零、你可能不需要 Redux 6 | - 首先明确一点,Redux 是一个有用的架构,但不是非用不可。事实上,大多数情况,你可以不用它,只用 React 就够了 7 | - 如果你不知道是否需要 Redux,那就是不需要它 8 | - 只有遇到 React 实在解决不了的问题,你才需要 Redux 9 | - 简单说,如果你的UI层非常简单,没有很多互动,Redux 就是不必要的,用了反而增加复杂性 10 | 11 | --- 12 | ### 一、预备知识 13 | - Redux 有很好的[文档](http://redux.js.org/),还有配套的小视频([前30集](https://egghead.io/courses/getting-started-with-redux),[后30集](https://egghead.io/courses/building-react-applications-with-idiomatic-redux))。你可以先阅读本文,再去官方材料详细研究 14 | 15 | --- 16 | ### 二、设计思想 17 | - Redux 的设计思想很简单,就两句话 18 | - Web 应用是一个状态机,视图与状态是一一对应的 19 | - 所有的状态,保存在一个对象里面 20 | 21 | --- 22 | ### 三、基本概念和 API 23 | 24 | #### 3.1 Store 25 | - Store 就是保存数据的地方,你可以把它看成一个容器。整个应用只能有一个 Store 26 | - Redux 提供`createStore`这个函数,用来生成 Store 27 | - `createStore`函数接受另一个函数作为参数,返回新生成的 Store 对象 28 | 29 | #### 3.2 State 30 | - `Store`对象包含所有数据。如果想得到某个时点的数据,就要对 Store 生成快照。这种时点的数据集合,就叫做 State 31 | - 当前时刻的 State,可以通过`store.getState()`拿到 32 | - Redux 规定, 一个 State 对应一个 View。只要 State 相同,View 就相同。你知道 State,就知道 View 是什么样,反之亦然 33 | 34 | #### 3.3 Action 35 | - State 的变化,会导致 View 的变化。但是,用户接触不到 State,只能接触到 View。所以,State 的变化必须是 View 导致的。Action 就是 View 发出的通知,表示 State 应该要发生变化了 36 | - Action 是一个对象。其中的`type`属性是必须的,表示 Action 的名称。其他属性可以自由设置 37 | - 改变 State 的唯一办法,就是使用 Action。它会运送数据到 Store 38 | 39 | #### 3.4 Action Creator 40 | - View 要发送多少种消息,就会有多少种 Action。如果都手写,会很麻烦。可以定义一个函数来生成 Action,这个函数就叫 Action Creator 41 | 42 | #### 3.5 store.dispatch() 43 | - `store.dispatch()`是 View 发出 Action 的唯一方法 44 | 45 | #### 3.6 Reducer 46 | - Store 收到 Action 以后,必须给出一个新的 State,这样 View 才会发生变化。这种 State 的计算过程就叫做 Reducer 47 | - Reducer 是一个函数,它接受 Action 和当前 State 作为参数,返回一个新的 State 48 | 49 | #### 3.7 纯函数 50 | - Reducer 函数最重要的特征是,它是一个纯函数。也就是说,只要是同样的输入,必定得到同样的输出 51 | - 纯函数是函数式编程的概念,必须遵守以下一些约束 52 | * 不得改写参数 53 | * 不能调用系统 I/O 的API 54 | * 不能调用`Date.now()`或者`Math.random()`等不纯的方法,因为每次会得到不一样的结果 55 | 56 | - 由于 Reducer 是纯函数,就可以保证同样的State,必定得到同样的 View。但也正因为这一点,Reducer 函数里面不能改变 State,必须返回一个全新的对象 57 | - 最好把 State 对象设成只读。你没法改变它,要得到新的 State,唯一办法就是生成一个新对象 58 | 59 | #### 3.8 store.subscribe() 60 | - Store 允许使用`store.subscribe`方法设置监听函数,一旦 State 发生变化,就自动执行这个函数 61 | - 显然,只要把 View 的更新函数(对于 React 项目,就是组件的`render`方法或`setState`方法)放入`listen`,就会实现 View 的自动渲染 62 | - `store.subscribe`方法返回一个函数,调用这个函数就可以解除监听 63 | 64 | --- 65 | ### 四、Store 的实现 66 | - 上一节介绍了 Redux 涉及的基本概念,可以发现 Store 提供了三个方法 67 | * store.getState() 68 | * store.dispatch() 69 | * store.subscribe() 70 | 71 | - `createStore`方法还可以接受第二个参数,表示 State 的最初状态。这通常是服务器给出的 72 | 73 | --- 74 | ### 五、Reducer 的拆分 75 | - Reducer 函数负责生成 State。由于整个应用只有一个 State 对象,包含所有数据,对于大型应用来说,这个 State 必然十分庞大,导致 Reducer 函数也十分庞大 76 | - Redux 提供了一个`combineReducers`方法,用于 Reducer 的拆分。你只要定义各个子 Reducer 函数,然后用这个方法,将它们合成一个大的 Reducer 77 | - 这种写法有一个前提,就是 State 的属性名必须与子 Reducer 同名。如果不同名,就要采用下面的写法 78 | - 总之,`combineReducers()`做的就是产生一个整体的 Reducer 函数。该函数根据 State 的 key 去执行相应的子 Reducer,并将返回结果合并成一个大的 State 对象 79 | 80 | --- 81 | ### 六、工作流程 82 | - 首先,用户发出 Action 83 | - 然后,Store 自动调用 Reducer,并且传入两个参数:当前 State 和收到的 Action。 Reducer 会返回新的 State 84 | - State 一旦有变化,Store 就会调用监听函数 85 | - `listener`可以通过`store.getState()`得到当前状态。如果使用的是 React,这时可以触发重新渲染 View 86 | 87 | --- 88 | ### 七、实例:计数器 89 | - [github: redux](https://github.com/reactjs/redux) 90 | - [Redux Counter Example](https://github.com/reactjs/redux/tree/master/examples/counter) 91 | -------------------------------------------------------------------------------- /Tutorial/08【阮一峰】Redux 入门教程(二):中间件与异步操作.md: -------------------------------------------------------------------------------- 1 | ### Redux 入门教程(二):中间件与异步操作 2 | [教程地址:Redux 入门教程(二):中间件与异步操作](http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_two_async_operations.html) 3 | 4 | --- 5 | - 一个关键问题没有解决:异步操作怎么办?Action 发出以后,Reducer 立即算出 State,这叫做同步;Action 发出以后,过一段时间再执行 Reducer,这就是异步。怎么才能 Reducer 在异步操作结束后自动执行呢?这就要用到新的工具:中间件(middleware) 6 | 7 | --- 8 | ### 一、中间件的概念 9 | - 为了理解中间件,让我们站在框架作者的角度思考问题:如果要添加功能,你会在哪个环节添加 10 | - (1)Reducer:纯函数,只承担计算 State 的功能,不合适承担其他功能,也承担不了,因为理论上,纯函数不能进行读写操作。 11 | - (2)View:与 State 一一对应,可以看作 State 的视觉层,也不合适承担其他功能。 12 | - (3)Action:存放数据的对象,即消息的载体,只能被别人操作,自己不能进行任何操作。 13 | 14 | - 中间件就是一个函数,对`store.dispatch`方法进行了改造,在发出 Action 和执行 Reducer 这两步之间,添加了其他功能 15 | 16 | --- 17 | ### 二、中间件的用法 18 | - `createStore`方法可以接受整个应用的初始状态作为参数,那样的话,`applyMiddleware`就是第三个参数了 19 | - 中间件的次序有讲究 20 | 21 | --- 22 | ### 三、applyMiddlewares() 23 | - `applyMiddlewares`这个方法是 Redux 的原生方法,作用是将所有中间件组成一个数组,依次执行 24 | 25 | --- 26 | ### 四、异步操作的基本思路 27 | - 理解了中间件以后,就可以处理异步操作了。同步操作只要发出一种 Action 即可,异步操作的差别是它要发出三种 Action 28 | * 操作发起时的 Action 29 | * 操作成功时的 Action 30 | * 操作失败时的 Action 31 | 32 | --- 33 | ### 五、redux-thunk 中间件 34 | - 暂时看不懂,不止从何整理 35 | 36 | --- 37 | ### 六、redux-promise 中间件 38 | - 既然 Action Creator 可以返回函数,当然也可以返回其他值。另一种异步操作的解决方案,就是让 Action Creator 返回一个 Promise 对象。这就需要使用`redux-promise`中间件 39 | -------------------------------------------------------------------------------- /Tutorial/09【阮一峰】Redux 入门教程(三):React-Redux 的用法.md: -------------------------------------------------------------------------------- 1 | 2 | ### Redux 入门教程(三):React-Redux 的用法 3 | [教程地址:Redux 入门教程(三):React-Redux 的用法](http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_three_react-redux.html) 4 | 5 | --- 6 | - 为了方便使用,Redux 的作者封装了一个 React 专用的库 [React-Redux](https://github.com/reactjs/react-redux) 7 | - 这个库是可以选用的。实际项目中,你应该权衡一下,是直接使用 Redux,还是使用 React-Redux。后者虽然提供了便利,但是需要掌握额外的 API,并且要遵守它的组件拆分规范 8 | 9 | 10 | --- 11 | ### 一、UI 组件 12 | - React-Redux 将所有组件分成两大类:UI 组件(presentational component)和容器组件(container component) 13 | - UI 组件有以下几个特征 14 | * 只负责 UI 的呈现,不带有任何业务逻辑 15 | * 没有状态(即不使用`this.state`这个变量) 16 | * 所有数据都由参数(`this.props`)提供 17 | * 不使用任何 Redux 的 API 18 | 19 | - 因为不含有状态,UI 组件又称为"纯组件",即它纯函数一样,纯粹由参数决定它的值 20 | 21 | --- 22 | ### 二、容器组件 23 | - 容器组件的特征恰恰相反 24 | * 负责管理数据和业务逻辑,不负责 UI 的呈现 25 | * 带有内部状态 26 | * 使用 Redux 的 API 27 | 28 | - 总之,只要记住一句话就可以了:UI 组件负责 UI 的呈现,容器组件负责管理数据和逻辑 29 | - ,如果一个组件既有 UI 又有业务逻辑,那怎么办?回答是,将它拆分成下面的结构:外面是一个容器组件,里面包了一个UI 组件。前者负责与外部的通信,将数据传给后者,由后者渲染出视图 30 | - React-Redux 规定,所有的 UI 组件都由用户提供,容器组件则是由 React-Redux 自动生成。也就是说,用户负责视觉层,状态管理则是全部交给它 31 | 32 | --- 33 | ### 三、connect() 34 | - React-Redux 提供`connect`方法,用于从 UI 组件生成容器组件。`connect`的意思,就是将这两种组件连起来 35 | - `connect`方法接受两个参数:`mapStateToProps`和`mapDispatchToProps`。它们定义了 UI 组件的业务逻辑。前者负责输入逻辑,即将`state`映射到 UI 组件的参数(`props`),后者负责输出逻辑,即将用户对 UI 组件的操作映射成 Action 36 | 37 | --- 38 | ### 四、mapStateToProps() 39 | - `mapStateToProps`是一个函数。它的作用就是像它的名字那样,建立一个从(外部的)`state`对象到(UI 组件的)`props`对象的映射关系 40 | - 作为函数,`mapStateToProps`执行后应该返回一个对象,里面的每一个键值对就是一个映射 41 | - `mapStateToProps`会订阅 Store,每当`state`更新的时候,就会自动执行,重新计算 UI 组件的参数,从而触发 UI 组件的重新渲染 42 | - `mapStateToProps`的第一个参数总是`state`对象,还可以使用第二个参数,代表容器组件的`props`对象 43 | 44 | --- 45 | ### 五、mapDispatchToProps() 46 | - `mapDispatchToProps`是`connect`函数的第二个参数,用来建立 UI 组件的参数到`store.dispatch`方法的映射。也就是说,它定义了哪些用户的操作应该当作 Action,传给 Store。它可以是一个函数,也可以是一个对象 47 | 48 | --- 49 | ### 六、`` 组件 50 | - `connect`方法生成容器组件以后,需要让容器组件拿到`state`对象,才能生成 UI 组件的参数 51 | - 一种解决方法是将`state`对象作为参数,传入容器组件。但是,这样做比较麻烦,尤其是容器组件可能在很深的层级,一级级将`state`传下去就很麻烦 52 | - React-Redux 提供`Provider`组件,可以让容器组件拿到`state` 53 | - `Provider`在根组件外面包了一层,这样一来,里面的所有子组件就默认都可以拿到`state`了 54 | - 它的原理是`React`组件的[`context`](https://facebook.github.io/react/docs/context.html)属性 55 | 56 | --- 57 | ### 七、实例:计数器 58 | - 完整的代码看[这里](https://github.com/jackielii/simplest-redux-example/blob/master/index.js) 59 | 60 | --- 61 | ### 八、React-Router 路由库 62 | - 使用`React-Router`的项目,与其他项目没有不同之处,也是使用`Provider`在`Router`外面包一层,毕竟`Provider`的唯一功能就是传入`store`对象 63 | - [一个react-redux的demo](https://github.com/cag2050/react_redux_demo161019) 64 | -------------------------------------------------------------------------------- /Tutorial/10 Redux 简明教程.md: -------------------------------------------------------------------------------- 1 | ### Redux 简明教程 2 | [教程地址:Redux 简明教程](https://github.com/kenberkeley/redux-simple-tutorial) 3 | 4 | --- 5 | ### 1. 为什么要用 Redux 6 | 比如有如下需求 7 | - 需求 1:在控制台上记录用户的每个动作 8 | - 需求 2:在上述需求的基础上,记录用户的操作时间 9 | - ... 10 | 11 | --- 12 | ### 2. Store 13 | - state 是应用的状态,一般本质上是一个普通对象 14 | - store 是应用状态 state 的管理者,包含下列四个函数 15 | * `getState() # 获取整个 state` 16 | * `dispatch(action) # ※ 触发 state 改变的【唯一途径】※` 17 | * `subscribe(listener) # 您可以理解成是 DOM 中的 addEventListener` 18 | * `replaceReducer(nextReducer) # 一般在 Webpack Code-Splitting 按需加载的时候用` 19 | 20 | - 二者的关系是:`state = store.getState()` 21 | - Redux 规定,一个应用只应有一个单一的 `store`,其管理着唯一的应用状态 `state`,Redux 还规定,不能直接修改应用的状态 `state` 22 | - 若要改变 `state`,必须 `dispatch` 一个 `action`,这是修改应用状态的不二法门 23 | - 上面提到,`state` 是通过 `store.getState()` 获取,那么 `store` 又是怎么来的呢?想生成一个 `store`,我们需要调用 Redux 的 `createStore` 24 | 25 | --- 26 | ### 3. Action 27 | - 上面提到,`action`(动作)实质上是包含 `type` 属性的普通对象,这个 `type` 是我们实现用户行为追踪的关键 28 | - 刨根问底,`action` 是谁生成的呢 29 | 30 | --- 31 | ### 4. Action Creator 32 | - Action Creator 可以是同步的,也可以是异步的 33 | - 顾名思义,Action Creator 是 `action` 的创造者,本质上就是一个**函数**,返回值是一个 `action`(**对象**) 34 | 35 | --- 36 | ### 5. Reducer 37 | - Reducer 必须是同步的纯函数 38 | - 用户每次 `dispatch(action)` 后,都会触发 `reducer` 的执行 39 | - `reducer` 的实质是一个**函数**,根据 `action.type` 来**更新** `state` 并返回 `nextState` 40 | - 最后会用 `reducer` 的返回值 `nextState` **完全替换掉**原来的 `state` 41 | - 注意:上面的这个 “更新” 并不是指 `reducer` 可以直接对 `state` 进行修改, Redux 规定,须先复制一份 `state`,在副本 `nextState` 上进行修改操作 42 | - 通俗点讲,就是 `reducer` 返回啥,`state` 就被替换成啥 43 | 44 | --- 45 | ### 6. 总结 46 | * `store` 由 Redux 的 `createStore(reducer)` 生成 47 | * `state` 通过 `store.getState()` 获取,本质上一般是一个存储着整个应用状态的**对象** 48 | * `action` 本质上是一个包含 `type` 属性的普通**对象**,由 Action Creator (**函数**) 产生 49 | * 改变 `state` 必须 `dispatch` 一个 `action` 50 | * `reducer` 本质上是根据 `action.type` 来更新 `state` 并返回 `nextState` 的**函数** 51 | * `reducer` 必须返回值,否则 `nextState` 即为 `undefined` 52 | * 实际上,**`state` 就是所有 `reducer` 返回值的汇总**(本教程只有一个 `reducer`,主要是应用场景比较简单) 53 | 54 | - Action Creator => `action` => `store.dispatch(action)` => `reducer(state, action)` => ~~`原 state`~~ `state = nextState` 55 | 56 | --- 57 | ### 7. 最简单的例子 58 | - [简单的在线演示例子](http://jsbin.com/zivare/edit?html,console) 59 | - 备注:Redux 除了和 React 一起用外,还支持其它界面库,是可以单独使用的,不一定要和react一起使用 60 | -------------------------------------------------------------------------------- /Tutorial/11【慕课网】在React中使用Redux数据流.md: -------------------------------------------------------------------------------- 1 | ### 在React中使用Redux数据流 2 | [教程地址:在React中使用Redux数据流](http://www.imooc.com/learn/744) 3 | 4 | --- 5 | ### 第1章 在React中使用Redux数据流--课程介绍 6 | #### 1-1 1 课程介绍 7 | - Redux维护了一个单一的状态树 8 | 9 | --- 10 | ### 第2章 在React中使用Redux数据流--基本概念 11 | #### 2-1 单向数据流 12 | - 介绍了点Flux 13 | 14 | #### 2-2 Redux介绍 15 | - 介绍Redux的处理流程 16 | 17 | --- 18 | ### 第3章 在React中使用Redux数据流--react回顾 19 | #### 3-1 React回顾 20 | - 快速回顾一下react 21 | 22 | ---- 23 | ### 第4章 介绍react-redux 24 | #### 4-1 react-redux安装及框架介绍 25 | - 当页面渲染完,UI就出现了,然后用户触发UI上的Action,然后Action被送到Reducer这个方法里去,然后Reducer更新了Store,Store里包含react开发的State,最后State决定UI层的展现。这就是Redux的一个完整过程 26 | - redux是可以以独立的库工作的,可以应用在普通的前端项目里,不是一定要应用在react里 27 | 28 | --- 29 | ### 第5章 学习react-redux 30 | #### 5-1 react-redux项目结构 31 | 项目的基本结构 32 | - actions:行为 33 | - components:UI组件 34 | - container:容器组件 35 | - reducer:Store里分发Action的方法 36 | - index.html:模板文件 37 | - server.js 38 | - webpack 39 | 40 | #### 5-2 action和reducer 41 | - **action**:1.是行为的抽象;2.是普通JS对象;3.一般由方法生成;4.必须有一个type 42 | - **reducer**:1.是响应的抽象;2.纯方法(非存方法是指比如依赖当前的时间) 43 | 44 | #### 5-3 介绍store 45 | - **store**:1.action作用于store;2.reducer根据store响应;3.对于redux来说,store是唯一的;4.store包括了完整的state;5.state完全可预测 46 | 47 | #### 5-4 介绍组件 48 | - 组件分为UI组件和容器组件,前者只负责展示,后者负责管理数据和传递数据给UI组件显示 49 | 50 | --- 51 | ### 第6章 开发样例工程 52 | #### 6-1 官方demo项目介绍 53 | >略 54 | 55 | #### 6-2 demo项目详解之项目结构 56 | >略 57 | 58 | #### 6-3 demo项目详解之action 59 | - 分析用户行为,设置Action Creator 60 | 61 | #### 6-4 demo项目详解之reducer1 62 | >略 63 | 64 | #### 6-5 demo项目详解之reducer2 65 | >略 66 | 67 | #### 6-6 demo项目详解之reducer3 68 | - 使用redux提供的combineReducers方法合并所有的reducer 69 | 70 | #### 6-7 demo项目详解之组件1 71 | - ref的一种新写法 72 | 73 | #### 6-8 demo项目详解之组件2 74 | - 卡在了`connect(mapStateToProps, mapDispatchToProps)()` 75 | 76 | #### 6-9 demo项目详解之组件3 77 | >懵 78 | 79 | #### 6-10 0 demo项目详解之入口文件包装 80 | - 在最外层包装了一个react-redux提供的Provider组件,将store当成props传递进去,被Provider包在内部的各级组件都能访问到store,其实现原理其实是用了react的context 81 | 82 | --- 83 | ### 第7章 在React中使用Redux数据流--扩展知识 84 | #### 7-1 扩展知识 85 | - react-redux: redux对react的绑定 86 | - redux-thunk: 实现异步action 87 | - redux-gen: 利用生成器去实现middleware 88 | - react-router-redux: 路由 89 | - react-redux-form: 表单提交 90 | 91 | --- 92 | ### 第8章 在React中使用Redux数据流--课程小结 93 | ####8-1 课程小结 94 | >略 95 | 96 | -------------------------------------------------------------------------------- /Tutorial/12 redux-tutorial.md: -------------------------------------------------------------------------------- 1 | ### redux-tutorial 2 | [英文原版地址](https://github.com/happypoulp/redux-tutorial) 3 | [中文翻译地址](https://github.com/react-guide/redux-tutorial-cn#redux-tutorial) 4 | 5 | --- 6 | ### 00. introduction 7 | >略 8 | 9 | --- 10 | ### 01. simple-action-creator 11 | - action creator 就是函数而已 12 | - 在后面的章节中,我们会发现 action creator 实际上可以返回 action 以外的其他东西,比如一个函数。 这在处理异步时很有用(更多的内容可以查阅 dispatch-async-action.js 13 | - 为了分发 action,我们需要...一个分发函数 14 | - 并且,为了让任何对它感兴趣的人都能感知到 action 发起,我们还需要一个注册“处理器(handlers)”的机制 15 | 16 | --- 17 | ### 02. about-state-and-meet-redux 18 | - Reducer 函数是 action 的订阅者 19 | - Reducer 函数只是一个纯函数,它接收应用程序的当前状态以及发生的 action,然后返回修改后的新状态 20 | - 如何把数据变更传播到整个应用程序——使用订阅者来监听状态的变更情况。 21 | - 总之 Redux 提供了: 22 | - 1)存放应用程序状态的容器 23 | - 2)一种把 action 分发到状态修改器的机制,也就是 reducer 函数 24 | - 3)监听状态变化的机制 25 | 26 | 创建一个store 27 | ```js 28 | import { createStore } from 'redux' 29 | var store = createStore(fn); 30 | ``` 31 | >注意createStore 函数必须接收一个能够修改应用状态的函数,否则报错 32 | 33 | --- 34 | ### 03. simple-reducer 35 | - 在创建一个 Redux 实例前(createStore前),需要给它一个 reducer 函数 36 | - 往 createStore 传 Reducer 的过程就是给 Redux 绑定 action 处理函数(也就是 Reducer)的过程 37 | - 在被调用时,一个 reducer 会得到这些参数:(state, action) 38 | - 在应用初始化时,Redux dispatch 了一个初始化的 action `({ type: '@@redux/INIT' })` 39 | - 在应用初始化时,state 还没被初始化,因此它的值是 "undefined" 40 | 41 | --- 42 | ### 04. get-state 43 | - 小结一下:调用 reducer ,只是为了响应一个派发来的 action 44 | 45 | --- 46 | ### 05. combine-reducers 47 | - Redux 不关心我们到底是只有一个 reducer ,还是有一打(12个)reducer 48 | - 如果我们有多个 reducer ,Redux 能帮我们合并成一个 49 | - 在这种多个 reducer 的模式下,我们可以让每个 reducer 只处理整个应用的部分 state 50 | - 但我们需要知道,createStore 只接收一个 reducer 函数 51 | - 那么,我们怎么合并所有的 reducer? 我们又该如何告诉 Redux 每个 reducer 只处理一部分 state 呢.其实这很简单。我们使用 combineReducers 辅助函数 52 | - combineReducers 接收一个对象并返回一个函数,当 combineReducers 被调用时,它会去调用每个reducer,并把返回的每一块 state 重新组合成一个大 state 对象(也就是 Redux 中的 Store) 53 | 54 | --- 55 | ### 06. dispatch-action 56 | - 用一个 action creator 去发送一个 action 57 | - 如果我们要在 dispatch action 之前做一些异步的操作,那应该怎么做呢 58 | - 至止,我们接触的应用流程是这样的:` ActionCreator -> Action -> dispatcher -> reducer` 59 | 60 | --- 61 | ### 07. dispatch-async-action 62 | >略 63 | 64 | --- 65 | ### 08. dispatch-async-action-2 66 | - 使用自定义中间件(middleware)来支持异步 action 67 | 68 | --- 69 | ### 09. middleware 70 | - 为了让 Redux 知道我们有一个或多个中间件,我们使用 Redux 的辅助函数:applyMiddleware. 71 | 72 | --- 73 | ### 10. state-subscriber 74 | - 使用 “provide” 和 “connect” 绑定,不必再关心隐含在内的订阅方法 75 | 76 | --- 77 | ### 11. Provider-and-connect 78 | >略 79 | 80 | --- 81 | ### 12. final-words 82 | >略 83 | -------------------------------------------------------------------------------- /Tutorial/13【Redux 中文文档】1.介绍.md: -------------------------------------------------------------------------------- 1 | ### Redux 中文文档 2 | [教程地址:Redux 中文文档](http://cn.redux.js.org/index.html) 3 | [英文原版](http://redux.js.org/) 4 | 5 | --- 6 | ### 目录 7 | ``` 8 | 1. 介绍 9 | 1.1. 动机 10 | 1.2. 核心概念 11 | 1.3. 三大原则 12 | 1.4. 先前技术 13 | 1.5. 生态系统 14 | 1.6. 示例 15 | 2. 基础 16 | 2.1. Action 17 | 2.2. Reducer 18 | 2.3. Store 19 | 2.4. 数据流 20 | 2.5. 搭配 React 21 | 2.6. 示例:Todo List 22 | 3. 高级 23 | 3.1. 异步 Action 24 | 3.2. 异步数据流 25 | 3.3. Middleware 26 | 3.4. 搭配 React Router 27 | 3.5. 示例:Reddit API 28 | 3.6. 下一步 29 | 4. 技巧 30 | 4.1. 迁移到 Redux 31 | 4.2. 使用对象展开运算符 32 | 4.3. 减少样板代码 33 | 4.4. 服务端渲染 34 | 4.5. 编写测试 35 | 4.6. 计算衍生数据 36 | 4.7. 实现撤销重做 37 | 4.8. 子应用隔离 38 | 4.9. 组织 Reducer 39 | 4.9.1. Reducer 基础概念 40 | 4.9.2. Reducer 基础结构 41 | 4.9.3. Reducer 逻辑拆分 42 | 4.9.4. Reducer 重构示例 43 | 4.9.5. `combineReducers` 用法 44 | 4.9.6. `combineReducers` 进阶 45 | 4.9.7. State 范式化 46 | 4.9.8. Updating Normalized Data 47 | 4.9.9. Reducer 逻辑复用 48 | 4.9.10. Immutable Update Patterns 49 | 4.9.11. 初始化 State 50 | 5. 常见问题 51 | 5.1. 综合 52 | 5.2. Reducer 53 | 5.3. 组织 State 54 | 5.4. 创建 Store 55 | 5.5. Action 56 | 5.6. 代码结构 57 | 5.7. 性能 58 | 5.8. React Redux 59 | 5.9. 其它 60 | 6. 排错 61 | 7. 词汇表 62 | 8. API 文档 63 | 8.1. createStore 64 | 8.2. Store 65 | 8.3. combineReducers 66 | 8.4. applyMiddleware 67 | 8.5. bindActionCreators 68 | 8.6. compose 69 | 9. react-redux 文档 70 | 9.1. API 71 | 9.2. 排错 72 | 10. redux-tutorial 73 | ``` 74 | 75 | --- 76 | ### 1. 介绍 77 | 78 | #### 1.1 动机 79 | - JavaScript 需要管理比任何时候都要多的 state (状态) 80 | - 复杂性很大程度上来自于:我们总是将两个难以理清的概念混淆在一起:变化和异步 81 | - 美中不足的是,React 依旧把处理 state 中数据的问题留给了你。Redux就是为了帮你解决这个问题 82 | - Redux 试图让 state 的变化变得可预测。这些限制条件反映在 Redux 的三大原则中 83 | 84 | #### 1.2 核心概念 85 | - 强制使用 action 来描述所有变化带来的好处是可以清晰地知道应用中到底发生了什么 86 | - action 就像是描述发生了什么的面包屑 87 | - 为了把 action 和 state 串起来,开发一些函数,这就是 reducer 88 | - reducer 只是一个接收 state 和 action,并返回新的 state 的函数 89 | 90 | #### 1.3 三大原则 91 | - Redux 可以用这三个基本原则来描述 92 | - 单一数据源 93 | - State 是只读的 94 | - 使用纯函数来执行修改 95 | - 整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中 96 | - 惟一改变 state 的方法就是触发 action,action 是一个用于描述**已发生事件**的普通对象 97 | - 为了描述 action 如何改变 state tree ,你需要编写 reducers 98 | 99 | #### 1.4 先前技术 100 | - 和 Flux 一样,Redux 规定,将模型的更新逻辑全部集中于一个特定的层(Flux 里的 store,Redux 里的 reducer) 101 | - Flux 和 Redux 都不允许程序直接修改数据,而是用一个叫作 “action” 的普通对象来对更改进行描述 102 | - 虽然出于性能方面的考虑,写不纯的 reducer 来变动数据在技术上是可行的,但我们并不鼓励这么做 103 | 104 | #### 1.5 生态系统 105 | - 很多有用的资料 106 | 107 | #### 1.6 示例 108 | >略(文档看完后再测试) 109 | -------------------------------------------------------------------------------- /Tutorial/14【Redux 中文文档】2. 基础.md: -------------------------------------------------------------------------------- 1 | ### Redux 中文文档 2 | [教程地址:Redux 中文文档](http://cn.redux.js.org/index.html) 3 | [英文原版](http://redux.js.org/) 4 | 5 | --- 6 | ### 目录 7 | ``` 8 | 1. 介绍 9 | 1.1. 动机 10 | 1.2. 核心概念 11 | 1.3. 三大原则 12 | 1.4. 先前技术 13 | 1.5. 生态系统 14 | 1.6. 示例 15 | 2. 基础 16 | 2.1. Action 17 | 2.2. Reducer 18 | 2.3. Store 19 | 2.4. 数据流 20 | 2.5. 搭配 React 21 | 2.6. 示例:Todo List 22 | 3. 高级 23 | 3.1. 异步 Action 24 | 3.2. 异步数据流 25 | 3.3. Middleware 26 | 3.4. 搭配 React Router 27 | 3.5. 示例:Reddit API 28 | 3.6. 下一步 29 | 4. 技巧 30 | 4.1. 迁移到 Redux 31 | 4.2. 使用对象展开运算符 32 | 4.3. 减少样板代码 33 | 4.4. 服务端渲染 34 | 4.5. 编写测试 35 | 4.6. 计算衍生数据 36 | 4.7. 实现撤销重做 37 | 4.8. 子应用隔离 38 | 4.9. 组织 Reducer 39 | 4.9.1. Reducer 基础概念 40 | 4.9.2. Reducer 基础结构 41 | 4.9.3. Reducer 逻辑拆分 42 | 4.9.4. Reducer 重构示例 43 | 4.9.5. `combineReducers` 用法 44 | 4.9.6. `combineReducers` 进阶 45 | 4.9.7. State 范式化 46 | 4.9.8. Updating Normalized Data 47 | 4.9.9. Reducer 逻辑复用 48 | 4.9.10. Immutable Update Patterns 49 | 4.9.11. 初始化 State 50 | 5. 常见问题 51 | 5.1. 综合 52 | 5.2. Reducer 53 | 5.3. 组织 State 54 | 5.4. 创建 Store 55 | 5.5. Action 56 | 5.6. 代码结构 57 | 5.7. 性能 58 | 5.8. React Redux 59 | 5.9. 其它 60 | 6. 排错 61 | 7. 词汇表 62 | 8. API 文档 63 | 8.1. createStore 64 | 8.2. Store 65 | 8.3. combineReducers 66 | 8.4. applyMiddleware 67 | 8.5. bindActionCreators 68 | 8.6. compose 69 | 9. react-redux 文档 70 | 9.1. API 71 | 9.2. 排错 72 | 10. redux-tutorial 73 | ``` 74 | 75 | --- 76 | ### 2. 基础 77 | - 不要被各种关于 reducers, middleware, store 的演讲所蒙蔽 —— Redux 实际是非常简单的。如果你有 Flux 开发经验,用起来会非常习惯。没用过 Flux 也不怕,很容易 78 | 79 | #### 2.1 Action 80 | - **Action** 是把数据从应用(译者注:这里之所以不叫 view 是因为这些数据有可能是服务器响应,用户输入或其它非 view 的数据 )传到 store 的有效载荷。它是 store 数据的**唯一**来源。一般来说你会通过 `store.dispatch()` 将 action 传到 store 81 | - Action 本质上是 JavaScript 普通对象。我们约定,action 内必须使用一个字符串类型的 `type` 字段来表示将要执行的动作。多数情况下,`type` 会被定义成字符串常量。当应用规模越来越大时,建议使用单独的模块或文件来存放 action 82 | 83 | #### 2.2 Reducer 84 | - **只要传入参数相同,返回计算得到的下一个 state 就一定相同。没有特殊情况、没有副作用,没有 API 请求、没有变量修改,单纯执行计算** 85 | - 最后,时刻谨记永远不要在克隆 `state` 前修改它 86 | - `combineReducers()` 所做的只是生成一个函数,这个函数来调用你的一系列 reducer,每个 reducer **根据它们的 key 来筛选出 state 中的一部分数据并处理**,然后这个生成的函数再将所有 reducer 的结果合并成一个大的对象 87 | 88 | #### 2.3 Store 89 | 90 | - **Store** 就是把它们联系到一起的对象。Store 有以下职责: 91 | * 维持应用的 state; 92 | * 提供`getState()` 方法获取 state; 93 | * 提供`dispatch(action)`方法更新 state; 94 | * 通过`subscribe(listener)` 注册监听器; 95 | * 通过`subscribe(listener)` 返回的函数注销监听器 96 | 97 | - 再次强调一下 **Redux 应用只有一个单一的 store**。当需要拆分数据处理逻辑时,你应该使用reducer 组合而不是创建多个 store 98 | 99 | - 根据已有的 reducer 来创建 store 是非常容易的.我们使用 `combineReducers()` 将多个 reducer 合并成为一个。现在我们将其导入,并传递 `createStore()` 100 | 101 | - `createStore()` 的第二个参数是可选的, 用于设置 state 初始状态。这对开发同构应用时非常有用,服务器端 redux 应用的 state 结构可以与客户端保持一致, 那么客户端可以将从网络接收到的服务端 state 直接用于本地数据初始化 102 | - 注意 subscribe() 返回一个函数用来注销监听器 103 | 104 | #### 2.4 数据流 105 | - **严格的单向数据流**是 Redux 架构的设计核心 106 | - Redux 应用中数据的生命周期遵循下面 4 个步骤 107 | - **1. 调用** `store.dispatch(action)` 108 | - Action 就是一个描述“发生了什么”的普通对象 109 | - 你可以在任何地方调用`store.dispatch(action)`,包括组件中、XHR 回调中、甚至定时器中 110 | 111 | - **2. Redux store 调用传入的 reducer 函数** 112 | - Store 会把两个参数传入reducer: 当前的 state 树和 action 113 | - 注意 reducer 是纯函数。它仅仅用于计算下一个 state。它应该是完全可预测的:多次传入相同的输入必须产生相同的输出。它不应做有副作用的操作,如 API 调用或路由跳转。这些应该在 dispatch action 前发生 114 | 115 | - **3. 根 reducer 应该把多个子 reducer 输出合并成一个单一的 state 树** 116 | - **4. Redux store 保存了根 reducer 返回的完整 state 树** 117 | 118 | 119 | #### 2.5 搭配 React 120 | - 这里需要再强调一下:Redux 和 React 之间没有关系。Redux 支持 React、Angular、Ember、jQuery 甚至纯 JavaScript 121 | - Redux 默认并不包含 React 绑定库,需要单独安装 122 | - Redux 的 React 绑定库是基于**容器组件**和**展示组件**相分离 的开发思想 123 | - 创建一些容器组件把这些展示组件和 Redux 关联起来 124 | - 技术上讲,容器组件就是使用 store.subscribe() 从 Redux state 树中读取部分数据,并通过 props 来把这些数据提供给要渲染的组件 125 | - 你可以手工来开发容器组件,但建议使用使用 React Redux 库的 connect() 方法来生成,这个方法做了性能优化来避免很多不必要的重复渲染。(这样你就不必为了性能而手动实现 React 性能优化建议 中的 shouldComponentUpdate 方法 126 | - 使用 `connect()` 前,需要先定义 `mapStateToProps` 这个函数来指定如何把当前 Redux store state 映射到展示组件的 props 中 127 | - 除了读取 state,容器组件还能分发 action。类似的方式,可以定义 `mapDispatchToProps()` 方法接收 `dispatch()`方法并返回期望注入到展示组件的 props 中的回调方法 128 | 129 | - 所有容器组件都可以访问 Redux store,所以可以手动监听它。一种方式是把它以 props 的形式传入到所有容器组件中。但这太麻烦了,因为必须要用 `store` 把展示组件包裹一层,仅仅是因为恰好在组件树中渲染了一个容器组件 130 | - 建议的方式是使用指定的 React Redux 组件 ``来 [魔法般的 让所有容器组件都可以访问 store,而不必显示地传递它。只需要在渲染根组件时使用即可 131 | 132 | 133 | -------------------------------------------------------------------------------- /Tutorial/15【Redux 中文文档】3. 高级.md: -------------------------------------------------------------------------------- 1 | ### Redux 中文文档 2 | [教程地址:Redux 中文文档](http://cn.redux.js.org/index.html) 3 | 4 | --- 5 | ### 目录 6 | ``` 7 | 1. 介绍 8 | 1.1. 动机 9 | 1.2. 核心概念 10 | 1.3. 三大原则 11 | 1.4. 先前技术 12 | 1.5. 生态系统 13 | 1.6. 示例 14 | 2. 基础 15 | 2.1. Action 16 | 2.2. Reducer 17 | 2.3. Store 18 | 2.4. 数据流 19 | 2.5. 搭配 React 20 | 2.6. 示例:Todo List 21 | 3. 高级 22 | 3.1. 异步 Action 23 | 3.2. 异步数据流 24 | 3.3. Middleware 25 | 3.4. 搭配 React Router 26 | 3.5. 示例:Reddit API 27 | 3.6. 下一步 28 | 4. 技巧 29 | 4.1. 迁移到 Redux 30 | 4.2. 使用对象展开运算符 31 | 4.3. 减少样板代码 32 | 4.4. 服务端渲染 33 | 4.5. 编写测试 34 | 4.6. 计算衍生数据 35 | 4.7. 实现撤销重做 36 | 4.8. 子应用隔离 37 | 4.9. 组织 Reducer 38 | 4.9.1. Reducer 基础概念 39 | 4.9.2. Reducer 基础结构 40 | 4.9.3. Reducer 逻辑拆分 41 | 4.9.4. Reducer 重构示例 42 | 4.9.5. `combineReducers` 用法 43 | 4.9.6. `combineReducers` 进阶 44 | 4.9.7. State 范式化 45 | 4.9.8. Updating Normalized Data 46 | 4.9.9. Reducer 逻辑复用 47 | 4.9.10. Immutable Update Patterns 48 | 4.9.11. 初始化 State 49 | 5. 常见问题 50 | 5.1. 综合 51 | 5.2. Reducer 52 | 5.3. 组织 State 53 | 5.4. 创建 Store 54 | 5.5. Action 55 | 5.6. 代码结构 56 | 5.7. 性能 57 | 5.8. React Redux 58 | 5.9. 其它 59 | 6. 排错 60 | 7. 词汇表 61 | 8. API 文档 62 | 8.1. createStore 63 | 8.2. Store 64 | 8.3. combineReducers 65 | 8.4. applyMiddleware 66 | 8.5. bindActionCreators 67 | 8.6. compose 68 | 9. react-redux 文档 69 | 9.1. API 70 | 9.2. 排错 71 | 10. redux-tutorial 72 | ``` 73 | 74 | --- 75 | ### 3. 高级 76 | - 基础章节介绍了如何组织简单的 Redux 应用。在这一章节中,将要学习如何使用 AJAX 和路由 77 | 78 | #### 3.1 异步 Action 79 | -------------------------------------------------------------------------------- /Tutorial/16【Redux 中文文档】4. 技巧.md: -------------------------------------------------------------------------------- 1 | ### Redux 中文文档 2 | [教程地址:Redux 中文文档](http://cn.redux.js.org/index.html) 3 | 4 | --- 5 | ### 目录 6 | ``` 7 | 1. 介绍 8 | 1.1. 动机 9 | 1.2. 核心概念 10 | 1.3. 三大原则 11 | 1.4. 先前技术 12 | 1.5. 生态系统 13 | 1.6. 示例 14 | 2. 基础 15 | 2.1. Action 16 | 2.2. Reducer 17 | 2.3. Store 18 | 2.4. 数据流 19 | 2.5. 搭配 React 20 | 2.6. 示例:Todo List 21 | 3. 高级 22 | 3.1. 异步 Action 23 | 3.2. 异步数据流 24 | 3.3. Middleware 25 | 3.4. 搭配 React Router 26 | 3.5. 示例:Reddit API 27 | 3.6. 下一步 28 | 4. 技巧 29 | 4.1. 迁移到 Redux 30 | 4.2. 使用对象展开运算符 31 | 4.3. 减少样板代码 32 | 4.4. 服务端渲染 33 | 4.5. 编写测试 34 | 4.6. 计算衍生数据 35 | 4.7. 实现撤销重做 36 | 4.8. 子应用隔离 37 | 4.9. 组织 Reducer 38 | 4.9.1. Reducer 基础概念 39 | 4.9.2. Reducer 基础结构 40 | 4.9.3. Reducer 逻辑拆分 41 | 4.9.4. Reducer 重构示例 42 | 4.9.5. `combineReducers` 用法 43 | 4.9.6. `combineReducers` 进阶 44 | 4.9.7. State 范式化 45 | 4.9.8. Updating Normalized Data 46 | 4.9.9. Reducer 逻辑复用 47 | 4.9.10. Immutable Update Patterns 48 | 4.9.11. 初始化 State 49 | 5. 常见问题 50 | 5.1. 综合 51 | 5.2. Reducer 52 | 5.3. 组织 State 53 | 5.4. 创建 Store 54 | 5.5. Action 55 | 5.6. 代码结构 56 | 5.7. 性能 57 | 5.8. React Redux 58 | 5.9. 其它 59 | 6. 排错 60 | 7. 词汇表 61 | 8. API 文档 62 | 8.1. createStore 63 | 8.2. Store 64 | 8.3. combineReducers 65 | 8.4. applyMiddleware 66 | 8.5. bindActionCreators 67 | 8.6. compose 68 | 9. react-redux 文档 69 | 9.1. API 70 | 9.2. 排错 71 | 10. redux-tutorial 72 | ``` 73 | 74 | --- 75 | ### 4. 技巧 76 | - 这一章是关于实现应用开发中会遇到的一些典型场景和代码片段。本章内容建立在你已经学会基础章节和高级章节的基础上 77 | 78 | #### 4.1 迁移到 Redux 79 | - Redux 不是一个单一的框架,而是一系列的约定和一些让他们协同工作的函数。你的 Redux 项目的主体代码甚至不需要使用 Redux 的 API,大部分时间你其实是在编写函数 80 | 81 | #### 4.2 使用对象展开运算符(Object Spread Operator) 82 | - 从不直接修改 state 是 Redux 的核心理念之一, 所以你会发现自己总是在使用`Object.assign()` 创建对象拷贝, 而拷贝中会包含新创建或更新过的属性值 83 | - 尽管这样可行, 但 `Object.assign()` 冗长的写法会迅速降低 reducer 的可读性 84 | - 一个可行的替代方案是使用 ES7 提案的 对象展开运算符。该提案让你可以通过展开运算符 (...) , 以更加简洁的形式将一个对象的可枚举属性拷贝至另一个对象 85 | - 当你在组合复杂对象时, 使用对象展开运算符带来的好处将更加突出 86 | - 目前对象展开运算符提案还处于 ECMAScript Stage 3 草案阶段, 若你想在产品中使用它得依靠转换编译器, 如 Babel 87 | 88 | #### 4.3 缩减样板代码 89 | - 将每个 action type 定义为 string 常量 90 | - 人们通常声称常量不是必要的。对于小项目也许正确。 对于大的项目,将 action types 定义为常量有很多好处 91 | 92 | #### 4.4 服务端渲染 93 | - 当在服务器使用 Redux 渲染时,一定要在响应中包含应用的 state,这样客户端可以把它作为初始 state 94 | 95 | #### 4.5 编写测试 96 | - 因为你写的大部分 Redux 代码都是些函数,而且大部分是纯函数,所以很好测,不需要模拟 97 | 98 | #### 4.6 计算衍生数据 99 | - Reselect 库可以创建可记忆的(Memoized)、可组合的 selector 函数。Reselect selectors 可以用来高效地计算 Redux store 里的衍生数据 100 | 101 | #### 4.7 实现撤销历史 102 | - 你可以用 Redux 轻而易举地实现撤销历史 103 | 104 | #### 4.8 子应用隔离 105 | - 为了使用 React API 来隐藏 Redux 的痕迹,在组件的构造方法里初始化 store 并把它包到一个特殊的组件中 106 | 107 | #### 4.9 组织 Reducer 108 | - 一些概念 109 | 110 | ##### 4.9.1 Reducer 基础概念 111 | - **核心概念** 112 | * 理解 state 和 state shape 113 | * 通过拆分 state 来确定各自的更新职责(**reducer 组合**) 114 | * 高阶 reducers 115 | * 定义 reducer 的初始化状态 116 | 117 | ##### 4.9.2 Reducer 和 State 的基本结构 118 | - 首先必须明确的是,整个应用只有一个**单一的 reducer 函数**:这个函数是传给 `createStore` 的第一个参数。 119 | - 一个单一的 reducer 最终需要做以下几件事 120 | * reducer 第一次被调用的时候,`state` 的值是 `undefined`。reducer 需要在 action 传入之前提供一个默认的 state 来处理这种情况。 121 | * reducer 需要先前的 state 和 dispatch 的 action 来决定需要做什么事。 122 | * 假设需要更改数据,应该用更新后的数据创建新的对象或数组并返回它们。 123 | * 如果没有什么更改,应该返回当前存在的 state 本身。 124 | 125 | - Redux 鼓励你根据要管理的数据来思考你的应用程序。数据就是你应用的 state,state 的结构和组织方式通常会称为 "shape" 126 | - 在你组织 reducer 的逻辑时,state 的 shape 通常扮演一个重要的角色 127 | - Redux state 中顶层的状态树通常是一个普通的 JavaScript 对象(当然也可以是其他类型的数据,比如:数字、数据或者其他专门的数据结构,但大多数库的顶层值都是一个普通对象) 128 | - 在顶层对象中组织数据最常见的方式是将数据划分为子树,每个顶层的 key 对应着和特定域或者切片相关联的数据 129 | 130 | ##### 4.9.3 拆分 Reducer 逻辑 131 | - 你可以将 reducer 中的一些逻辑拆分出去,然后在父函数中调用这个新的函数,这些新的函数通常分为三类: 132 | - 一些小的工具函数,包含一些可重用的逻辑片段 133 | - 用于处理特定情况下的数据更新的函数,参数除了 `(state, action)` 之外,通常还包括其它参数 134 | - 处理给定 state 切片的所有更新的函数,参数格式通常为 `(state, action)` 135 | 136 | 为了清楚起见,这些术语将用于区分不同类型的功能和不同的用例 137 | * **reducer:** 任何符合 `(state, action) -> newState` 格式的函数(即,可以用做 `Array.reducer` 参数的任何函数)。 138 | * **root reducer:** 通常作为 `createStore` 第一个参数的函数。他是唯一的一个在所有的 reducer 函数中必须符合 `(state, action) -> newState` 格式的函数。 139 | * **slice reducer:** 一个负责处理状态树中一块切片数据的函数,通常会作为 `combineReducers` 函数的参数。 140 | * **case function:** 一个负责处理特殊 action 的更新逻辑的函数。可能就是一个 reducer 函数,也可能需要其他参数才能正常工作。 141 | * **higher-order reducer:** 一个以 reducer 函数作为参数,且/或返回一个新的 reducer 函数的函数(比如: `combineReducers`, `redux-undo`) 142 | 143 | #### 4.9.4 使用函数分解和Reducer组合重构Reducer 144 | >我觉得重构后更加复杂了 145 | 146 | #### 4.9.5 使用 `combineReducers` 147 | - 一个常见的问题是 Reducer 在 dispatch action 的时候是否调用了所有的 reducer。当初你可能觉得“不是”,因为真的只有一个根 reducer 函数啊。但是 `combineReducer` 确实有着这样的特殊效果。在生成新的 state 树时,`combinerReducers` 将调用每一个拆分之后的 reducer 和与当前的 Action,如果有需要的话会使得每一个 reducer 有机会响应和更新拆分后的 state。所以,在这个意义上, `combineReducers`会调用所有的 reducer,严格来说是它包装的所有 reducer 148 | 149 | - 这里有两种方式来定义 Store state 的初始结构和内容 150 | - 首先,`createStore` 函数可以将 `preloadedState` 作为第二个参数。这主要用于初始化那些在其他地方有持久化存储的 state,例如浏览器的 localStorage 151 | - 另外一种方式是当 state 是 `undefined` 的时候返回 initial state 152 | - `combineReducers` 接收拆分之后的 reducer 函数组成的对象,并且创建出具有相同键对应状态对象的函数。这意味着如果没有给 `createStore` 提供预加载 state,输出 state 对象的 key 将由输入的拆分之后 reducer 组成对象的 key 决定。这些名称之间的相关性并不总是显而易见的,尤其是在使用 ES6 的时候(如默认模块搭配出和对象字面量的简写方向时) 153 | 154 | ##### 4.9.6 combineReducers 进阶 155 | - 一种解决“共享片段数据更新”的方法是把所需数据当额外参数的形式传递给自定义函数 156 | - 另一种解决“共享片段数据更新” (shared-slice updates) 问题的简单方法是,给 action 添加额外数据。可以通过 thunk 函数或者类似的方法轻松实现 157 | 158 | #### 4.9.9 Reducer 逻辑复用 159 | - 正如在 Reducer 逻辑拆分 定义的那样,高阶 reducer 是一个接收 reducer 函数作为参数,并返回新的 reducer 函数的函数 160 | 161 | #### 4.9.11 初始化 State 162 | - 主要有两种方法来初始化应用的 state 163 | - 可以使用 createStore 方法中的第二个可选参数 preloadedState 164 | - 也可以在 reducer 中为 undefined 的 state 参数指定的默认的初始值。这个可以通过在 reducer 中添加一个明确的检查来完成,也可以使用 ES6 中默认参数的语法 function myReducer(state = someDefaultValue, action) 165 | 166 | - 通常情况下,通过 preloadedState 指定的 state 要优先于通过 reducer 指定 state。这样可以使通过 reducer 默认参数指定初始数据显得更加的合理 167 | -------------------------------------------------------------------------------- /Tutorial/17【Redux 中文文档】5. 常见问题.md: -------------------------------------------------------------------------------- 1 | ### # Redux 常见问题 2 | [教程地址:Redux 常见问题](http://cn.redux.js.org/index.html) 3 | 4 | --- 5 | ### 目录 6 | ``` 7 | 1. 介绍 8 | 1.1. 动机 9 | 1.2. 核心概念 10 | 1.3. 三大原则 11 | 1.4. 先前技术 12 | 1.5. 生态系统 13 | 1.6. 示例 14 | 2. 基础 15 | 2.1. Action 16 | 2.2. Reducer 17 | 2.3. Store 18 | 2.4. 数据流 19 | 2.5. 搭配 React 20 | 2.6. 示例:Todo List 21 | 3. 高级 22 | 3.1. 异步 Action 23 | 3.2. 异步数据流 24 | 3.3. Middleware 25 | 3.4. 搭配 React Router 26 | 3.5. 示例:Reddit API 27 | 3.6. 下一步 28 | 4. 技巧 29 | 4.1. 迁移到 Redux 30 | 4.2. 使用对象展开运算符 31 | 4.3. 减少样板代码 32 | 4.4. 服务端渲染 33 | 4.5. 编写测试 34 | 4.6. 计算衍生数据 35 | 4.7. 实现撤销重做 36 | 4.8. 子应用隔离 37 | 4.9. 组织 Reducer 38 | 4.9.1. Reducer 基础概念 39 | 4.9.2. Reducer 基础结构 40 | 4.9.3. Reducer 逻辑拆分 41 | 4.9.4. Reducer 重构示例 42 | 4.9.5. `combineReducers` 用法 43 | 4.9.6. `combineReducers` 进阶 44 | 4.9.7. State 范式化 45 | 4.9.8. Updating Normalized Data 46 | 4.9.9. Reducer 逻辑复用 47 | 4.9.10. Immutable Update Patterns 48 | 4.9.11. 初始化 State 49 | 5. 常见问题 50 | 5.1. 综合 51 | 5.2. Reducer 52 | 5.3. 组织 State 53 | 5.4. 创建 Store 54 | 5.5. Action 55 | 5.6. 代码结构 56 | 5.7. 性能 57 | 5.8. React Redux 58 | 5.9. 其它 59 | 6. 排错 60 | 7. 词汇表 61 | 8. API 文档 62 | 8.1. createStore 63 | 8.2. Store 64 | 8.3. combineReducers 65 | 8.4. applyMiddleware 66 | 8.5. bindActionCreators 67 | 8.6. compose 68 | 9. react-redux 文档 69 | 9.1. API 70 | 9.2. 排错 71 | 10. redux-tutorial 72 | ``` 73 | 74 | --- 75 | ### 5.1 Redux 常见问题:综合 76 | - **何时使用 Redux** 77 | - 在打算使用 Redux 的时候进行权衡是非常重要的。它从设计之初就不是为了编写最短、最快的代码,他是为了解决 “当有确定的状态发生改变时,数据从哪里来” 这种可预测行为的问题的 78 | - 如果你只是刚开始学习 React,你应该首先专注于 React,然后再看看 Redux 是否适合于你的应用 79 | - 最后需要说明的是:Redux 仅仅是个工具。它是一个伟大的工具,经常有一个很棒的理由去使用它,但也有很多的理由不去使用它。时刻注意对你的工具做出明确的决策,并且权衡每个决策带来的利弊 80 | 81 | ### 5.2 Redux 常见问题:Reducer 82 | - 许多用户想在 reducer 之间共享数据,但是 `combineReducers` 不允许此种行为。有许多可用的办法 83 | * 如果一个 reducer 想获取其它 state 层的数据,往往意味着 state 树需要重构,需要让单独的 reducer 处理更多的数据。 84 | * 你可能需要自定义方法去处理这些 action,用自定义的顶层 reducer 方法替换 `combineReducers`。你可以使用类似于reduce-reducers 的工具运行 `combineReducers` 去处理尽可能多的 action,同时还要为存在 state 交叉部分的若干 action 执行更专用的 reducer。 85 | * 类似于 `redux-thunk` 的异步 action 创建函数 能通过 `getState()` 方法获取所有的 state。 action 创建函数能从 state 中检索到额外的数据并传入 action,所以 reducer 有足够的信息去更新所维护的 state 层 86 | 87 | ### 5.3 Redux 常见问题:组织 State 88 | - **必须将所有 state 都维护在 Redux 中吗? 可以用 React 的 `setState()` 方法吗** 89 | - 没有 “标准”。有些用户选择将所有数据都在 Redux 中维护,那么在任何时刻,应用都是完全有序及可控的。也有人将类似于“下拉菜单是否打开”的非关键或者 UI 状态,在组件内部维护。适合自己的才是最好的 90 | - 使用局部组件状态是更好的。作为一名开发者,应该决定使用何种 state 来组装你的应用,每个 state 的生存范围是什么。在两者之间做好平衡,然后就去做吧 91 | - 有许多开源组件实现了各式各样在 Redux store 存储独立组件状态的替代方法 92 | 93 | ### 5.4 Redux 常见问题:创建 Store 94 | >略 95 | 96 | #### 5.5 Redux 常见问题:Action 97 | >略 98 | 99 | #### 5.6 Redux 常见问题:代码结构 100 | - 因为 Redux 只是数据存储的库,它没有关于工程应该被如何组织的直接主张。然后,有一些被大多数 Redux 开发者所推荐的模式: 101 | * Rails-style:“actions”、“constants”、“reducers”、“containers” 以及 “components” 分属不同的文件夹 102 | * Domain-style:为每个功能或者域创建单独的文件夹,可能会为某些文件类型创建子文件夹 103 | * “Ducks”:类似于 Domain-style,但是明确地将 action、 reducer 绑定在一起,通常将它们定义在同一文件内 104 | 105 | #### 5.7 Redux 常见问题:性能 106 | >略 107 | 108 | #### 5.8 Redux 常见问题:React Redux 109 | >略 110 | 111 | #### 5.9 Redux 常见问题:其它 112 | - 如何在 Redux 中实现鉴权 113 | -------------------------------------------------------------------------------- /Tutorial/README.md: -------------------------------------------------------------------------------- 1 | # 目录 2 | --------------------------------------------------------------------------------