跳至主内容
非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

核心概念

假设你的应用状态被描述为一个普通对象。例如,一个待办事项应用的状态可能如下所示:

{
todos: [{
text: 'Eat food',
completed: true
}, {
text: 'Exercise',
completed: false
}],
visibilityFilter: 'SHOW_COMPLETED'
}

这个对象类似于"模型",但它没有设置器。这样设计是为了防止代码的不同部分随意更改状态,导致难以复现的 bug。

要修改状态中的内容,你需要分发一个动作(action)。动作是一个普通的 JavaScript 对象(注意我们并没有引入任何魔法?),用于描述发生了什么。以下是一些动作示例:

{ type: 'ADD_TODO', text: 'Go to swimming pool' }
{ type: 'TOGGLE_TODO', index: 1 }
{ type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }

强制要求每个变更都描述为动作,这让我们能清晰理解应用中发生的一切。如果有任何变化,我们都能知道原因。动作就像是事件发生的痕迹记录。最后,为了将状态和动作关联起来,我们会编写一个称为 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 来管理应用的完整状态,每个 reducer 对应各自的状态键:

function todoApp(state = {}, action) {
return {
todos: todos(state.todos, action),
visibilityFilter: visibilityFilter(state.visibilityFilter, action)
}
}

这基本上就是 Redux 的全部理念。请注意,我们尚未使用任何 Redux API。Redux 提供了一些工具来简化这种模式,但核心思想是:描述状态如何随时间响应动作对象而更新,而你编写的 90% 代码都是纯 JavaScript,无需使用 Redux 本身、其 API 或任何魔法。