1 | http://redux.js.org/ |
简介
Redux 由 Flux 演变而来,但受 Elm 的启发,避开了 Flux 的复杂性
1 | import { createStore } from 'redux'; |
Redux 没有 Dispatcher 且不支持多个 store。相反,只有一个单一的 store 和一个根级的 reduce 函数(reducer)
中间件
1 | redux-thunk — 用最简单的方式搭建异步 action 构造器 |
三大原则
Redux 可以用这三个基本原则来描述:
单一数据源
整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中
State 是只读的
惟一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象
使用纯函数来执行修改
为了描述 action 如何改变 state tree ,你需要编写 reducers;Reducer 只是一些纯函数,它接收先前的 state 和 action,并返回新的 state
总结
- 应用中所有的 state 都以一个对象树的形式储存在一个单一的 store 中
- 惟一改变 state 的办法是触发 action,一个描述发生什么的对象
- 为了描述 action 如何改变 state 树,你需要编写 reducers
- 编写专门的函数来决定每个 action 如何改变应用的 state,这个函数被叫做 reducer
安装
- 安装redux:npm install redux --save
- 使用 React 绑定库和开发者工具:npm install react-redux --save;npm install redux-devtools --save-dev
原理
Action
Action 是把数据从应用传到 store 的有效载荷,它是 store 数据的唯一来源。一般来说会通过 store.dispatch() 将 action 传到 store。
action 内必须使用一个字符串类型的 type 字段来表示将要执行的动作.多数情况下,type 会被定义成字符串常量,建议使用单独的模块或文件来存放 action。除了 type 字段外,action 对象的结构完全由自己决定
1 | import { ADD_TODO, REMOVE_TODO } from '../actionTypes' |
Action 创建函数
Action 创建函数 就是生成 action 的方法
1 | function addTodo(text) { |
bindActionCreators() 可以自动把多个 action 创建函数 绑定到 dispatch() 方法上。
Reducer
永远不要在 reducer 里做这些操作:
- 修改传入参数;
- 执行有副作用的操作,如 API 请求和路由跳转;
- 调用非纯函数,如 Date.now() 或 Math.random()
1 | function todoApp(state = initialState, action) { |
- 不要修改 state。 使用 Object.assign() 新建了一个副本。不能这样使用 Object.assign(state, { visibilityFilter: action.filter }),因为它会改变第一个参数的值。你必须把第一个参数设置为空对象。你也可以开启对ES7提案对象展开运算符的支持, 从而使用 { …state, …newState } 达到相同的目的。
- 在 default 情况下返回旧的 state
- Object.assign() 是 ES6 特性,但多数浏览器并不支持。你要么使用 polyfill,Babel 插件,或者使用其它库如 _.assign() 提供的帮助方法。
- 新的 todos 对象就相当于旧的 todos 在末尾加上新建的 todo。而这个新的 todo 又是基于 action 中的数据创建的
Store
Store 有以下职责:
- 维持应用的 state;
- 提供 getState() 方法获取 state;
- 提供 dispatch(action) 方法更新 state;
- 通过 subscribe(listener) 注册监听器;
- 通过 subscribe(listener) 返回的函数注销监听器
搭配react
Redux 和 React 之间没有关系。Redux 支持 React、Angular、Ember、jQuery 甚至纯 JavaScript。
连接到 Redux:我们需要做出两个变化,将 App 组件连接到 Redux 并且让它能够 dispatch actions 以及从 Redux store 读取到 state
- 获取从之前安装好的 react-redux 提供的 Provider,并且在渲染之前将根组件包装进
1 | //index.js |
- 通过 react-redux 提供的 connect() 方法将包装好的组件连接到Redux
1 | import React, { Component, PropTypes } from 'react'; |