问题描述
在我的应用程序的许多地方发生以下模式:
In many places in my app the following pattern happens:
- 用户点击一些链接触发导航
- 需要获取数据以呈现视图
- UI 设计需要在获取数据时显示加载"微调器
- 获取数据后,我们将显示渲染视图
我已经尝试了以下两种实现模式:
I have tried both of the following implementation patterns:
路由器处理获取
Router handles fetching
- Router 告诉容器视图显示加载微调器
- 路由器加载任何集合/模型
- Router 告诉容器视图隐藏加载微调器
- Router 将集合/模型传递给视图并呈现它
视图句柄获取
- Router 只是创建并渲染视图
- 视图获取它需要的集合和模型
- 第一次渲染视图时,它只显示加载微调器,因为数据仍在加载
- 当数据到达时,模型/集合会触发事件,并且视图绑定到这些事件,因此它会重新渲染自身,从而隐藏加载微调器并显示完整视图
我不喜欢 #1,因为路由器变成了模型/集合获取逻辑的巨大球,并且似乎有太多的责任.#2 似乎是更好的职责分配(路由器只是决定显示哪个视图,视图确定它需要获取哪些数据),但它确实使视图呈现有点棘手,因为它现在是有状态的.
I dislike #1 since the router becomes a gigantic ball of Model/Collection fetching logic and seems to have too much responsibility. #2 seems like a better allocation of responsibilities (router just decides which view to show, view figures out what data it needs to fetch), but it does make the view rendering a little trickier since it's stateful now.
StackOverflow 社区是怎么想的?1、2 还是其他?
What does the StackOverflow community think? 1, 2, or something else?
推荐答案
这篇文章已经很旧了,但我们今天早些时候正在审查它,以防其他人遇到它:
This post is pretty old, but we were reviewing it earlier today, so in case anyone else comes across it:
对我来说,我真的看到了 2 个不同的问题:
To me, I really see 2 separate questions:
- 数据获取机制和结果视图渲染应该发生在路由器还是视图中?
- 视图应该期待已经解析的模型,还是应该响应可能仍在加载的模型?
我们如何处理它并结合一些个人喜好:
A bit of how we handle it mixed with some personal preferences:
- 都没有,尽管我会更靠近路由器.路由器应该处理路由,视图应该处理查看,其他东西应该处理模型/集合获取逻辑的机制和工作流.我们称其为控制器,路由器基本上委托给它.
- 正如尤里所暗示的那样,有时"是现实.我认为这可能是个案决定,但最终应该是控制器和视图之间的契约,而不是路由器/视图之间的契约.
我喜欢 Yuri 的要点,有几个警告(缩进的项目符号):
I like Yuri's bullet points, with a couple caveats (indented bullets):
- 路由器只知道将用户发送到哪里
- 外部视图只知道用户应该查看什么(给定数据)
- 假设外部视图特定于内部视图的用例并且由另一个视图拥有"(用于清理)
- 否则对于通用容器(例如渲染到主"位置),我们发现有一个组件来管理页面上某个部分"的视图很有用 - 我们称之为渲染器
- 对于通用容器,最终由渲染器负责
Renderer 的主要原因是处理与该部分相关的事情,例如清理现有视图以避免出现鬼视图、在渲染时滚动到顶部(我们的 MainContentRenderer 会这样做),或者在这种情况下显示微调器.
The main reason for the Renderer is to handle things related to that section, like cleaning up existing views to avoid ghost views, scrolling to the top on render (our MainContentRenderer does that), or showing a spinner in this case.
一个可能看起来像的伪代码示例,用于:
A psuedo-code-ish example of what that might look like, for:
- 通用内容目标main"(如果它是特定于用例的,根据 Yuri 的示例,使用 ComponentView 可能会更好,具体取决于您的视图生命周期管理策略)
- 我们必须获取并等待的模型
- 接受已加载模型的视图
路由器:
routes: { "profile": "showProfile" }, showProfile: function() { return new ProfileController().showProfile(); }
配置文件控制器:
showProfile: function() { //simple case var model = new Model(); var deferredView = model.fetch.then(function() { return new View(model); }; MainContentRenderer.renderDeferred(deferredView); }
MainContentRenderer:
var currentView; renderDeferred: function(deferredView) { showSpinner(); deferredView.then(function(view) { this.closeSpinner(); this.closeCurrentView(); this.render(view); } }, render: function(view) { currentView = view; $('#main-content').html(view.render().el); } closeCurrentView: function() { if (currentView and currentView.close()) { currentView.close(); } }
引入控制器还具有可测试性的额外好处.例如,我们有复杂的规则来执行围绕 URL 管理的搜索、在结果视图和新搜索视图之间进行选择,以及在缓存的上次"搜索结果和执行新搜索之间进行选择.我们对控制器进行了 Jasmine 测试,以验证所有流程逻辑是否正确.它还提供了一个隔离的地方来管理这些规则.
Introducing a Controller also has the added benefit of testability. For example, we have complex rules for performing searches around URL management, picking between a results view and a new search view, and picking between a cached 'last' search result and executing a new search. We have Jasmine tests for the controllers to verify that all that flow logic is correct. It also provides an isolated place to manage these rules.
这篇关于骨干路由器或视图是否应该处理获取数据和显示加载状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!