1.概念javascript
通俗理解reduxhtml
2.actionjava
(1)本质是一个JS对象;react
3.reducerredux
(1)Store 收到 Action 之后,必须给出一个新的 State,这样 View 才会发生变化。这种 State 的计算过程就叫作 Reducer。数组
(2)接受action和当前参数state做为参数,而后返回一个新的statedom
const reducer = function (state, action) { // ... return new_state; };
例子:异步
const defaultState = 0; const reducer = (state = defaultState, action) => { switch (action.type) { case 'ADD': return state + action.payload; default: return state; } }; const state = reducer(1, { type: 'ADD', payload: 2 });
实际应用中,Reducer 函数不用像上面这样手动调用,store.dispatch方法会触发 Reducer 的自动执行。为此,Store 须要知道 Reducer 函数,作法就是在生成 Store 的时候,将 Reducer 传入createStore方法。ide
import { createStore } from 'redux'; const store = createStore(reducer);
createStore
接受 Reducer 做为参数,生成一个新的 Store。之后每当store.dispatch
发送过来一个新的 Action,就会自动调用 Reducer,获得新的 State。函数
// State 是一个对象 function reducer(state, action) { //后面的thingTochange会覆盖前面的state return Object.assign({}, state, { thingToChange }); // 或者,对象展开符的对象合并,后面有的属性会覆盖前面的 return { ...state, ...newState }; } // State 是一个数组 function reducer(state, action) { //在数组里面添加一个项目,若是后面的也是一个数组,直接...new Item return [...state, newItem]; }
(3)reducer是一个纯函数。
一样的输入一定致使一样的输出。
4.store
(1)createStore函数接受另外一个函数做为参数,返回新生成的Store对象 。store对象包含全部数据。
(2)一个state对应一个view,只要state相同,view就相同,因此state的变化会致使view的变化。
用户接触不到state,只接触view,因此,state的变化是view致使的,action是view发出的通知,表示State应该要变化了。
action是一个对象,type属性必须,其余能够自由设置,通常会有payload action描述当前发生的事情,改变State的惟一办法,就是使用Action。
store.dispatch()是view发出action的惟一方法。
(3)
Store 容许使用store.subscribe
方法设置监听函数,一旦 State 发生变化,就自动执行这个函数。
import { createStore } from 'redux'; const store = createStore(reducer); store.subscribe(listener);
显然,只要把 View 的更新函数(对于 React 项目,就是组件的render
方法或setState
方法)放入listen
,就会实现 View 的自动渲染。
store.subscribe
方法返回一个函数,调用这个函数就能够解除监听。
let unsubscribe = store.subscribe(() => console.log(store.getState()) ); unsubscribe();
5.react-redux
react项目中,能够直接使用redux,也可使用react-redux,后者需掌握额外的API,而且遵循它的组件拆分规范。
(1)react-redux将全部组件分为:UI组件和容器组件
UI组件最大特征是没有this.state(无状态),只负责UI的呈现,不带有任何业务逻辑,不使用redux的API;
容器组件:负责管理数据和业务逻辑,不负责UI呈现,带有内部状态,使用redux的API。
使用react-redux,若是一个组件既有UI又有逻辑,那么将它拆分红下面结构:外面是一个容器组件,里面包含一个UI组件,前者负责与外部通讯,将数据传给后者,由后者渲染出视图。
react-redux规定:全部UI组件都由用户提供,容器组件则由react-redux自动生成,也就是说,用户负责视觉层,状态管理则所有交给它。
(2)connect()
react-redux提供connect方法,用于从UI组件生成容器组件。connect的意思,就是将二者连起来。
import { connect } from 'react-redux' const VisibleTodoList = connect( mapStateToProps, mapDispatchToProps )(TodoList)
mapStateToProps:输入逻辑,即将state
映射到 UI 组件的参数(props
)。做为函数,返回一个对象,里面的每个键值对就是一个映射。
mapStateToProps
会订阅 Store,每当state
更新的时候,就会自动执行,从新计算 UI 组件的参数,从而触发 UI 组件的从新渲染。
mapStateToProps
的第一个参数老是state
对象,还可使用第二个参数,表明容器组件的props
对象。
使用ownProps
做为参数后,若是容器组件的参数发生变化,也会引起 UI 组件从新渲染。
connect
方法能够省略mapStateToProps
参数,那样的话,UI 组件就不会订阅Store,就是说 Store 的更新不会引发 UI 组件的更新。
mapDispatchToProps()
mapDispatchToProps
是connect
函数的第二个参数,用来创建 UI 组件的参数到store.dispatch
方法的映射。也就是说,它定义了哪些用户的操做应该看成 Action,传给 Store。它能够是一个函数,也能够是一个对象。
若是mapDispatchToProps
是一个函数,会获得dispatch
和ownProps
(容器组件的props
对象)两个参数。
mapDispatchToProps
做为函数,应该返回一个对象,该对象的每一个键值对都是一个映射,定义了 UI 组件的参数怎样发出 Action。
若是mapDispatchToProps
是一个对象,它的每一个键名也是对应 UI 组件的同名参数,键值应该是一个函数,会被看成 Action creator ,返回的 Action 会由 Redux 自动发出。
(3)<Provider>组件
connect
方法生成容器组件之后,须要让容器组件拿到state
对象,才能生成 UI 组件的参数。
一种解决方法是将state
对象做为参数,传入容器组件。可是,这样作比较麻烦,尤为是容器组件可能在很深的层级,一级级将state
传下去就很麻烦。
React-Redux 提供Provider
组件,可让容器组件拿到state
。
import { Provider } from 'react-redux' import { createStore } from 'redux' import todoApp from './reducers' import App from './components/App' let store = createStore(todoApp); render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') )
Provider在根组件外面包了一层,这样一来,App的全部子组件就默认均可以拿到state了。
6.问题E
(1)为何叫作reducer?
由于它能够做为数组的reduce
方法的参数。
const actions = [ { type: 'ADD', payload: 0 }, { type: 'ADD', payload: 1 }, { type: 'ADD', payload: 2 } ]; const total = actions.reduce(reducer, 0); // 3
(2)什么叫纯函数?
一样输入致使一样输出。
一些约束:
Date.now()
或者Math.random()
等不纯的方法,由于每次会获得不同的结果。(3)redux怎么解决异步的问题?
Action 发出之后,Reducer 当即算出 State,这叫作同步;Action 发出之后,过一段时间再执行 Reducer,这就是异步。
依靠使用中间件(middleware)。
(4)Provider的原理
是React组件的context属性。
store放在了上下文对象context上面,而后子组件就能够从context拿到store。
Provider的惟一功能就是传入store对象。