Redux中的多态性和动作冒泡?

时间:2015-10-16 11:30:24

标签: reactjs polymorphism hierarchy abstract-syntax-tree redux

我正在使用Redux(+ React)来操作分层结构,我有两个问题:

  1. 如何在Redux中实现多态?
  2. 如何制作“动作冒泡”
  3. 我的问题更精确地表达了:

    1. 我正在使用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事件冒泡(这完全是其他事情)。我我想减少行动泡沫。当我写“冒泡”时我会考虑整体设计模式而不是实施。

      这些是我的两个问题:)

2 个答案:

答案 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)

  1. 多态性
  2. 当您提到创建小型可重用功能时,我认为您已经找到了答案。我不同意多态性是一个更好的选择。 Redux是关于函数式编程的,而不是庞大的继承树。

    1. 动作冒泡。
    2. 请记住,在Redux / Flux中,您的商店是您唯一的真相来源。您的视图组件(即React元素)从商店中获取其数据。信息(即道具)从您的根元素自上而下流向其子元素,然后流向其子元素等

      因此,您需要做的就是更新您的商店。其余的照顾自己。信息泡沫,但不是直接从孩子到父母。相反,它从孩子到商店(通过一个动作),然后再到父母。