例如,假设我们有一个页面,显示一个包含10行和2列的表格。每行都有一个产品字段和一个金额字段。金额字段具有一个范围输入,范围为[0, 10]。用户可以单独设置每个产品的金额。
用户还通过使用两个按钮获得了2个选项。
按下第二个按钮将禁用表格中除第一个产品以外的所有产品(有效地将它们的金额设置为0,用户不能再与它们交互以设置它们的金额)。让我们称之为“选项B”。
按下第一个按钮将启用第一个产品后的所有产品(默认情况下为每个产品设置其金额为1),用户可以再次与它们交互,单独设置它们的金额。让我们称之为“选项A”。
此“应用程序”的状态由以下简单对象描述:
state = {
option : <String>,
products : [
{
name : <String>,
amount : <Integer>
}, ...
]
}
我们还有这4个简单的action创建者:
function setOption(option) {
return { type : 'SET_OPTION', option : option};
}
function incAmount(productName) {
return {
type : 'INCREMENT_AMOUNT',
product : productName
}
}
function decAmount(productName) {
return {
type : 'DECREMENT_AMOUNT',
product : productName
}
}
function setAmount(productName, amount) {
return {
type : 'SET_AMOUNT',
payload : { product : productName, amount : amount }
}
}
为了简单起见,我们只有一个 reducer。
在这个例子中,选择 选项 B
应该对状态产生以下影响:
- 将
option
更改为B
- 将第一个之后的每个
product
的数量设为0
选择 选项 A
应该分别对状态产生以下影响:
- 将
option
更改为A
- 将第一个之后的每个
product
的数量设为1
增加产品 A 的数量应该对状态产生以下影响:
- 将产品 A 的数量增加 1
实现这些更改的正确方法是什么?
a) 在 option
按钮的 onClick
处理程序中执行以下操作:
- 触发
store.dispatch(setOption(option))
- 对于第一个之后的每个产品都要触发
store.dispatch(setAmount(productName, amount))
(amount
= 1 表示选项 A,0 表示选项 B)
b) 在 option
按钮的 onClick
处理程序中执行以下操作:
触发
store.dispatch(setOption(option))
并且让 reducer 更改每个之后产品的
option
以及数量为指定的数量(amount
= 1 表示选项 A,0 表示选项 B)
如果我们选择 a),则 reducer 中 switch (action) {}
语句中的每种情况都只处理状态的一个方面,但我们必须从一个 click
事件中触发多个动作。
如果我们选择 b),则我们只需要从 click
事件中触发一个动作,但是 reducer 中 SET_OPTION
的情况不仅会更改 option
,还会更改产品的 amount
。