Redux 3 - 入门:核心概念(Core Concepts)
这里先上一张redux的工作流程图, 便于理解下面代码
用一个简单对象来描述应用的状态。可以把Todo应用的状态如下描述:
{
todos: [{
text: 'Eat food',
completed: true
}, {
text: 'Exercise',
completed: false
}],
visibilityFilter: 'SHOW_COMPLETED'
}
这个对象看起来像“model”,但与“model”有一个重要的区别是禁止set操作。就是说在代码的不同部分不能随意更改状态——这种随意性往往会带来难以调试的bug。
如果要更改state需要派发一个Action。Action是一个用来描述应用变化情况的简单JavaScirpt对象(注意这里不存在任何魔术)。下面是几个Action的例子:
{ type: 'ADD_TODO', text: 'Go to swimming pool' }
{ type: 'TOGGLE_TODO', index: 1 }
{ type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }
强制规定将每一次变化都描述为一个Action对象,使得我们可以清晰的理解程序中发生变化的情况。对于这些变化,清晰的知道为什么变化。Action就像程序中发生变化情况的面包屑。 最后,再通过Reducer方法,将State和Action结合在一起。再次注意,这里不存在什么魔术事件,Reducer仅仅是一个普通方法,接收State和Action作为参数,并返回应用的下一个状态。 很难将一个庞大的应用状态都用一个方法来处理状态,可以将其拆分成若干个较小的方法组合来管理状态的各个部分:
function visibilityFilter(state = 'SHOW_ALL', action) {
if (action.type === 'SET_VISIBILITY_FILTER') {
return action.filter;
} else {
return state;
}
}
function todos(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return state.concat([{ text: action.text, completed: false }]);
case 'TOGGLE_TODO':
return state.map((todo, index) =>
action.index === index ?
{ text: todo.text, completed: !todo.completed } :
todo
)
default:
return state;
}
}
最后编写一个单独的总Reducer,通过相关键(编者按:下例中和方法同名的键)来管理上述两个Reducer方法,以形成完整的应用状态:
function todoApp(state = {}, action) {
return {
todos: todos(state.todos, action),
visibilityFilter: visibilityFilter(state.visibilityFilter, action)
};
}
至此基本上就把Redux的全部思想介绍完了。注意目前没有使用任何Redux的API。Redux的API只是用来帮助实现该思想模式的一组工具方法,编码的关键是如何将随着时间变化的响应的状态描述为Action对象,90%的工作都是在编写简单JavaScript对象,这不会涉及到Redux本身,也不会涉及到它的API,更没有什么魔法。