19

我发现示例 todo Flux 应用程序有点缺乏,所以我试图通过开发一个应用程序来学习和实验来了解情况。

该应用程序是一个拖放式水果篮组织器。我有几个篮子,可以在它们之间拖着各种水果。您可以通过单击突出显示一个水果,最后拖动的项目将保持突出显示。

基于此,我有 3 家商店:

  • 水果店
  • 篮子商店
  • AppStateStore - 跟踪最后点击和最后拖动的水果

当用户操作发生时,如果水果已被单击,则由 AppStateStore 调度和处理 FruitAction,如果已将水果移动到另一个篮子,则由所有商店处理。

主 AppView 组件侦听来自 FruitStore 和 AppStateStore 的更改事件并重新渲染。

我的问题是:

  • 这是这种情况的好方法吗?
  • AppView 是否应该监听多个商店?我应该如何防止 AppView 连续渲染多次?现在,当水果被移动时,FruitStore 和 AppStateStore 都会触发更改事件,导致连续两次渲染。
  • React 网站上的 Flux 文章显示了调度动作对象的视图(例如 AppDispatcher.dispatch(TodoActions.updateText()) ),但如果动作自己调度(例如 FruitActions.moveBasket() )并且 AppView 是不知道 AppDispatcher?
  • 目前只有 AppView 监听商店,但如果要突出显示,单个 Fruit 组件是否应该监听 AppStateStore 以仅重新渲染它们自己?
  • 是否有更完整的 Flux 架构或类似的示例?
4

2 回答 2

13
  • 这种方法听起来很可靠。我会为每次交互创建完全不同的动作,例如FruitClickedFruitDragged两者都可以是动作,商店会关注他们关心的动作。
  • AppView应该收听它从中获取数据的所有商店。如果你setState在同一个滴答声中调用了不止一次,React 会智能地合并它们,所以你实际上并没有渲染不止一次。
  • React 网站上的文章确实讨论了在创建语义操作下调度自己的操作。在代码块中向上滚动几页,您可以看到代码:

    _onDestroyClick: function() { 
      TodoActions.destroy(this.props.todo.id); 
    } 
    
  • 这篇文章还讨论了哪些组件应该在Listening to Changes with a Controller-View中监听存储:

    我们需要一个靠近组件层次结构顶部的 React 组件来监听 store 中的变化。在一个更大的应用程序中,我们会有更多这样的监听组件,也许页面的每个部分都有一个。在 Facebook 的广告创建工具中,我们有许多类似控制器的视图,每个视图都管理 UI 的特定部分。在 Lookback Video Editor 中,我们只有两个:一个用于动画预览,一个用于图像选择界面。

    有时我们可能需要在层次结构更深处添加额外的控制器视图以保持组件简单。这可能有助于我们更好地封装与特定数据域相关的层次结构部分。但是请注意,层次结构中更深的控制器视图可能会通过为数据流引入一个新的、潜在冲突的入口点来违反单一的数据流。在决定是否添加深度控制器视图时,平衡简单组件的增益与在不同点流入层次结构的多个数据更新的复杂性。这些多次数据更新可能会导致奇怪的效果,React 的渲染方法会被来自不同控制器视图的更新反复调用,这可能会增加调试的难度。

  • 如果您对通量架构感兴趣,您可能会对Fluxxor感兴趣(免责声明:我写了它),它(希望)有助于构建基于通量的应用程序。它有一个更健壮的调度程序和一些其他更改(例如非全局存储/操作,React 混合),在许多情况下使事情变得更容易一些。
于 2014-05-29T16:14:47.453 回答
5

如果不进一步了解应用程序,很难说这种方法是否好。

但是,在我看来,点击水果应该由 FruitStore 处理。也就是说,一个水果已经获得了活跃状态,变成了可拖动的。如果这会以某种方式影响整个应用程序,那么也许这也会导致 AppStateStore 发生变化。同样,将水果从一个篮子转移到另一个篮子似乎是 BasketStore 的领域。

我想象 FruitStore 包含这样的私有数据结构:

var _fruit = {
  1234: {
    id: '1234',
    type: 'apple',
    active: false
  },
  2345: {
    id: '2345',
    type: 'orange',
    active: false
  },
  3456: {
    id: '3456',
    type: 'apple',
    active: false
  }
};

我想象 BasketStore 有一个看起来像这样的私有数据结构:

var _baskets = {
  4321: {
    id: '4321',
    name: 'Josephine\'s Basket',
    fruitIDs: [
      1234,
      2345
    ]
  },
  5432: {
    id: '5432',
    name: 'Harold\'s Basket',
    fruitIDs: [
      3456
    ]
  }
};

因此,水果“活动”状态由 FruitStore 管理,而篮子中的内容由 BasketStore 管理。

因此,如果这对您的应用程序有效,AppView 可以监听这两个商店。如上所述,重复调用 render() 方法的成本非常低。这不会在每次调用时都触及 DOM——这是 React 的最大优势之一。React 将智能地批处理调用,并且仅更新 DOM 的“脏”部分(如果存在)。

但也许你可能想让篮子变成控制器视图。如果您确实选择让您的水果成为控制器视图,请务必在 componentWillUnmount() 中清理侦听器,因为水果从篮子到篮子的移动可能需要销毁并重新创建它们。我认为在篮子级别聆听更有意义,但同样,我不太了解您的应用程序。

要回答您的最后一个问题:

是否有更完整的 Flux 架构或类似的示例?

Facebook 的工程师现在正在研究一个更复杂的应用程序示例,该示例将展示 waitFor() 和服务器端持久存储的使用。我们希望尽快发布。

于 2014-07-05T18:36:12.103 回答