我正在使用Redux(+ React)来操作分层结构,我有两个问题:
我的问题更精确地表达了:
我正在使用Redux在React中制作结构代码编辑器。通过结构编辑器,我的意思是我有树结构,其中包含节点,我的应用程序应该在AST而不是纯文本上运行。
这些节点可以有各种类型(因为它是编辑CSS文件的编辑器,例如:“rule”,“declaration”,“property”,“value”,但更重要的是它们确实有某种类型在所有)。因此,JS中的对象具有属性type
,其type
确定其...类型;)
假设我有这样的节点:
{
type: 'property',
id: 4,
rule: '.content > ul > li',
children: [...blah blah......]
}
我希望能够写出类似的内容:
store.dispatch({type: 'click', nodeId: 4})
点击。但是我希望单击rule
类型的节点比单击property
类型的节点有其他效果。多态性(但我希望有一个反应组件<Node />
来防止代码重复)。
我知道我可以通过switch / case或者自己的子函数来实现(我的意思是将动作委托给函数),但我不想重新发明轮子。我认为对多态的支持对许多应用程序都很有用,不仅仅是我的。
那么 - 如何在Redux中实现多态?
2,
关于行动冒泡的第二个问题。因为像这样的例子我有树结构:
{
type: 'rule',
rule: 'body div',
id: 1,
children: [
{
type: 'declaration',
id: 2,
children: [
{type: 'property', name: 'display', id: 3},
{type: 'value', value: 'block', id: 4},
]
}
]
}
我有适当的React组件来渲染该结构(我有基于函数的无状态React 0.14组件,所以我认为组件的代码现在不是很重要)。无论如何,我得到了代表单个AST节点的<Node/>
组件。
我希望该用户可以点击例如id = 3({type: 'property', name: 'display', id: 3},
)的节点,并且操作会自动“冒泡”到节点的父节点(在这种情况下为id = 2的声明节点并且规则id = 1的节点。
据我所知,Redux中没有“动作冒泡”。也许它应该是?或者也许我想通过其他方式实现的目标是什么? (通过“动作冒泡”我的意思是类似于浏览器中JavaScript事件中的“事件冒泡”,只是我希望redux actions
冒泡并且我不希望DOM事件冒泡(这完全是其他事情)。我我想减少行动泡沫。当我写“冒泡”时我会考虑整体设计模式而不是实施。
这些是我的两个问题:)
答案 0 :(得分:2)
我认为这是一个很好的问题,基于我对redux的理解,减速器违反了Open Closed和Single Responsibility原则,因为他们在同一个reducer上你可以处理多个事件,如果你想添加其他处理程序你需要更改减速机代码...
// This is kind of the standard approach
// It has a big switch case that knows how to handle many actions (single responsibility violation).
// The more actions you have the bigger this function becomes, to handle an other even you need to change the reducer (open closed violation).
export default function reducer(state = INITIAL_STATE, action) {
switch (action.type) {
case 'SET_ENTRIES':
return setEntries(state, action.payload);
case 'NEXT':
return next(state);
case 'VOTE':
return vote(state, action.payload)
}
// return the current state if the action you try to use dont exist
return state;
}
在上面的情况下,操作将类似{type: 'VOTE', payload: {...}}
...我个人不喜欢这种方法,因为它不灵活,我认为通过使用多态下面是一个更灵活的多态减速器的例子:
// This is a polymorphic aprorach that conforms to all SOLID principles
// This is much simpler and will raise an error if the action does not exist
export default function reducer(state = INITIAL_STATE, action) {
return action.handler(state, action.payload);
}
在上面的案例中,操作看起来像{handler: vote, payload: {...}}
这种方法更加灵活,您甚至可以使用该方法创建一次性{handler: (state) => { ... }}
。
答案 1 :(得分:0)
当您提到创建小型可重用功能时,我认为您已经找到了答案。我不同意多态性是一个更好的选择。 Redux是关于函数式编程的,而不是庞大的继承树。
请记住,在Redux / Flux中,您的商店是您唯一的真相来源。您的视图组件(即React元素)从商店中获取其数据。信息(即道具)从您的根元素自上而下流向其子元素,然后流向其子元素等
因此,您需要做的就是更新您的商店。其余的照顾自己。信息泡沫,但不是直接从孩子到父母。相反,它从孩子到商店(通过一个动作),然后再到父母。