redux模式的原理此处不再赘述,以下主要参考了Redux详解,以及阮一峰老师的博客,其他内容可以参考我的前一篇博客:react学习笔记系列(二)
类比vux,就是状态管理
(1)Web 应用是一个状态机,视图与状态是一一对应的。
(2)所有的状态,保存在一个对象里面。
createStore
这个函数,用来生成 Store。State
:store
对象中的定义的初始数据(初始状态)。Store
对象包含所有数据。如果想得到某个时点的数据,就要对 Store 生成快照。这种时点的数据集合,就叫做 State。当前时刻的 State,可以通过store.getState()
拿到。reducer里面定义初始状态,它是reducer函数的第一个参数action
就是视图View
发出的通知,表示state
要发生改变;Action 是一个对象。其中的type
属性是必须的,表示 Action 的名称。const action = {
type: 'ADD_TODO', //Action 的名称是ADD_TODO
payload: 'Learn Redux' //携带的信息是字符串Learn Redux。
};
Action creator:View
要发送多少种消息,就会有多少种 action
;通过action creator
(action 创建函数)生成action
,用来改变state
状态。它是reducer函数的第二个参数store.dispatch()
是View
发出action
的唯一方法,store.dispatch
接受一个 action
对象作为参数,将它发送出去。import { createStore } from 'redux';
const store = createStore(fn);
store.dispatch({
type: 'ADD_TODO',
payload: 'Learn Redux'
});
state
改变的规则即:store
收到action
后,必须给出新的state
,这样view
才会发生变化;这种state
的计算过程就叫做reducer
;Reducer 是一个函数,它接受 Action 和当前 State 作为参数,返回一个新的 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
方法。也就是说:
import { createStore } from 'redux';
const store = createStore(reducer);
为什么叫reducer呢:因为它可以作为数组的reduce
方法的参数
const actions = [
{ type: 'ADD', payload: 0 },
{ type: 'ADD', payload: 1 },
{ type: 'ADD', payload: 2 }
];
const total = actions.reduce(reducer, 0); // 3
由于 Reducer 是纯函数,就可以保证同样的State,必定得到同样的 View。但也正因为这一点,Reducer 函数里面不能改变 State,必须返回一个全新的对象(利用es6的扩展运算符)
// State 是一个对象
function reducer(state, action) {
return Object.assign({}, state, { thingToChange });
// 或者
return { ...state, ...newState };
}
// State 是一个数组
function reducer(state, action) {
return [...state, newItem];
}
store.subscribe()Store 允许使用store.subscribe
方法设置监听函数,一旦 State 发生变化,就自动执行这个函数。store.subscribe
方法返回一个函数,调用这个函数就可以解除监听。有关于store的实现,reducer的拆分,待细看
redux的中间件:
定义:中间件就是一个函数,对store.dispatch
方法进行了改造,在发出 Action 和执行 Reducer 这两步之间,添加了其他功能。
常用的中间件:redux-logger:用来打印日志
import createLogger from 'redux-logger';
有关于react-redux:
※dumb component(es5写法stateless component)
※smart component
React-Redux 规定,所有的 UI (dumb)组件都由用户提供,容器组件(smart)则是由 React-Redux 自动生成。也就是说,用户负责视觉层,状态管理则是全部交给它。 |
connect
方法,用于从 UI 组件生成容器组件。connect
的意思,就是将这两种组件连起来。(1)输入逻辑:外部的数据(即state
对象)如何转换为 UI 组件的参数
(2)输出逻辑:用户发出的动作如何变为 Action 对象,从 UI 组件传出去。
import { connect } from 'react-redux'
const VisibleTodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
// 容器组件的代码
//
// All
//
const mapStateToProps = (state, ownProps) => {
return {
active: ownProps.filter === state.visibilityFilter
}
}
//mapStateToProps是一个函数,它接受state作为参数,返回一个对象。mapStateToProps的第一个参数总是state对象,还可以使用第二个参数,代表容器组件的props对象。
//mapStateToProps会订阅 Store,每当state更新的时候,就会自动执行,重新计算 UI 组件的参数,从而触发 UI 组件的重新渲染。
//mapDispatchToProps是connect函数的第二个参数,用来建立 UI 组件的参数到store.dispatch方法的映射。也就是说,它定义了哪些用户的操作应该当作 Action,传给 Store。它可以是一个函数,也可以是一个对象。
上面代码中,connect
方法接受两个参数:mapStateToProps
和mapDispatchToProps
。它们定义了 UI 组件的业务逻辑。前者负责输入逻辑,即将state
映射到 UI 组件的参数(props
),后者负责输出逻辑,即将用户对 UI 组件的操作映射成 Action
connect
方法生成容器组件以后,需要让容器组件拿到state
对象,才能生成 UI 组件的参数。React-Redux 提供Provider
组件,可以让容器组件拿到state
。
References:
使用真正的 Redux 和 React-redux
Redux详解
Redux 入门教程(一):基本用法
Redux 入门教程(二):中间件与异步操作
Redux 入门教程(三):React-Redux 的用法