简介
基本概念
随着单页面应用需求越来越复杂,应用需要管理的状态也变得越来越多。这里的状态不仅包括从服务器端获取的数据,还包括本地创建的数据,同样也包括反映 UI 状态的数据,例如当前路由的位置、选中的标签、弹出框的控制等。Redux 通过一系列约定的规范将修改应用状态的步骤标准化,让应用状态的管理不再错综复杂,而是如同一根长线般清晰。
下面通过一个简单的例子阐述 Redux 的核心概念。本章项目源代码的目录为 /chapter-08/todos-redux。假设我们要开发一个待办事项 todos 的应用,用一个 JavaScript 对象描述这个应用的状态:
{
"todos": [{
"text": 'Learn React',
"completed": true
}, {
"text": 'Learn Redux',
"completed": false
}],
"visibilityFilter": 'SHOW_COMPLETED'
}
todos 包含所有的事项,包括已经完成的和尚未完成的,根据 completed 属性区分该事项是否已经完成;visibilityFilter 是一个过滤条件,表示当前界面上应该显示哪些事项。这个对象需要被视为只读对象,当需要修改应用状态时,必须发送一个 action,action 描述应用状态应该如何修改,其实 action 只是一个普通的 JavaScript 对象。例如,当新增一个待办事项时,可以发送下面的 action:
{ "type": 'ADD_TODO', "text": 'Learn MobX' }
type 代表 action 的类型,此处 ADD_TODO 表示要新增一个待办事项,text 包含新增事项的内容。类似地,如果要让界面显示所有的事项,可以发送下面的 action:
{ "type": 'SET_VISIBILITY_FILTER', "filter": 'SHOW_ALL' }
注意,action 的结构并不是确定的(但必须包含 type 字段),不同的人有不同的描述习惯,例如,可以通过 action 描述新增一个待办事项:
{ "type": 'ADD', "data": 'Learn MobX' }
只要保证你的程序知道如何解析定义的 action 即可。那么,如何解析 action 呢?Redux 通过 reducer 解析 action。reducer 是一个普通的 JavaScript 函数,接收 action 为参数,然后返回一个新的应用状态 state。例如,这里我们定义一个 reducer(省略处理 state 的逻辑代码):
function todoApp(state={}, action) {
switch(action.type) {
case SET_VISIBILITY_FILTER:
// return new state
case ADD_TODO:
// return new state
case TOGGLE_TODO:
// return new state
default:
return state
}
}
todoApp 就是管理应用全局 state 的 reducer,todoApp 每次返回的 state 的结构就是最初定义的应用状态的结构:
{
"todos": [...],
"visibilityFilter": ...
}
这一系列过程描述了 Redux 的基本概念。Redux 的主要思想就是描述应用的状态如何根据 action 进行更新,Redux 通过提供一系列 API 将这一主要思想的落地实施进行标准化和规范化。但就 Redux 的使用者而言,编写的绝大部分代码都是普通的 JavaScript 代码,只有在个别地方会用到 Redux 的 API 而已。