体系结构问题-使用子路由与组件

时间:2018-12-01 16:20:06

标签: ember.js architecture

我正在尝试构建一个UI,其左侧栏具有过滤器,而右侧具有实际过滤的数据。 要将数据加载到UI的动态部分(右侧),从代码质量和应用程序性能方面考虑,哪种方法更好?

  • 使用子路由(用于用户界面的动态部分)
  • 使用单独的组件来加载自己的数据(对于动态部分 用户界面)

2 个答案:

答案 0 :(得分:4)

对此没有直接正确的答案;您可以同时使用两种方法,但是这里有一些要考虑的因素,最后由于以下原因,我通常更喜欢使用子路由:

  1. 正在等待加载UI :如果您要使用单独的组件来加载其自己的数据,请执行以下操作:那么您需要处理组件的加载状态。我的意思是;如果您只是使用子路线;然后模型挂钩(modelbeforeModel等)将在显示数据之前等待承诺被解决。如果仅提供加载模板(请参见details的指南),则默认情况下将显示该模板。如果使用组件,则可能需要显示叠加层/旋转条以提供更好的用户体验。
  2. 错误处理:类似于加载状态管理; Ember已经内置了对路由挂钩方法中的错误处理的支持。如果您希望使用组件进行远程调用,则需要自己处理。 (请参见details的指南)
  3. 应用程序状态:Ember是SPA框架;通常的做法是将应用程序状态与URL同步。如果您使用子路线;您只需使用查询参数(请参见details的指南),便可以与其他人共享URL,并且应用程序将以相同状态加载。对组件执行相同操作比较棘手;您仍然需要在路由内使用查询参数,并将参数传递给组件以实现此目的。
  4. 使用组件挂钩方法::如果您打算使用组件,则很可能需要使用组件挂钩方法打开具有默认filter值的应用程序。这意味着您将需要在initwillRenderdidReceiveAttrs组件挂钩方法中的一个或多个中对服务器进行一些远程调用。我个人不喜欢在这些方法中进行远程调用。因为我觉得最好在路由内完成,并且应该将数据传递给组件;但这是我个人的编码习惯,您应该以不同的方式处理这种情况,这很好。

答案 1 :(得分:1)

数据减少,动作增加使组件保持灵活性

在您的特定示例中,我将提出第三个选项:发出动作的单独组件,由路由的控制器加载其数据的组件,以及从不直接与DDAU对齐地操纵其传递的参数。

我将有一个组件search-filter searchParams=searchParams onFilterChange=(action 'filterChanged')用于搜索过滤器,还有一个组件search-results data=searchResults用于显示数据。

首先让我们看一下搜索过滤器。使用操作为您提供了最大的灵活性,因为搜索过滤器仅在更改时发出某种搜索对象。您的控制器动作如下所示:

actions: {
  filterChanged(searchParams){
     this.set('searchParams', searchParams);
     //make the search and then update `searchResults`
  }
}

,这意味着您的search-filter组件会将所有搜索过滤器字段汇总到一个搜索对象中,该对象用作onFilterChange的唯一参数。

您现在可能会想,“好吧,为什么不从组件内部进行搜索呢?”您可以,但是以DRY的方式进行操作将意味着在加载时,首先将参数传递给组件,在didInsertElement上进行默认搜索,这会在操作中产生结果,并更新{{1} }值。我发现这种控制流程不是最明显的。此外,您可能需要发出一个searchResults回调,然后如果搜索操作/可以一起应用哪些搜索过滤器参数的操作有条件地取决于应用程序中的页面,则可能会发出其他操作/帮助程序选项。

一个组件,它带有一个搜索对象,并在每次搜索过滤器字段更改时发出一个动作,因此很简单。由于onSearchError是单向绑定的,因此在模板中使用此组件的任何searchParams都可以控制字段是否更新(通过在无效情况下选择阻止route的更新)或是否根据searchParams之间的验证规则触发搜索。另外,在单元测试期间没有模拟依赖关系。

在使用子路由之前,请三思而后行

对于您问题的routes部分,我发现深度嵌套的路线几乎始终是反模式。深入地说,我的意思是超越subroutes,第一个孩子是一种类似于菜单的结构,它通过简单的app->first-child->second child助手来控制second child级别上不同显示之间的切换。如果我必须在父母与子女之间共享状态,那么我将创建{{link-to}}服务而不是进行first-child-routes-shared-statemodelFor歌舞。

在使用子项controllerFor与把手route {{if}}部分进行辩论时,您还必须考虑后退按钮的行为应该返回上一步还是返回到您输入整体之前的路线部分。在创建->审核->完成后的电汇向导中,我真的应该能够在完成付款后从完成按后退按钮进行审核?

{{else}} + searchFilter的情况下,他们对我来说总是走同一条路。如果搜索值需要在URL刷新时保持不变,则选择查询参数。

最后,请注意,仅因为displayData意味着嵌套,您也可以只使用/users/:id/profile并完全避免嵌套。