这个问题,简而言之:
在 MVC 中,您如何区分复选框单击(或选择框或列表框更改)与人类含义“控制器,修改模型”,以及复选框单击(或选择框或列表框更改)与控制器含义“我”我更新视图,因为模型已经改变”?
这个例子:
我有一个 JS 应用程序(都是一个大的 HTML+JS 页面;它后面有一个服务器,并且 AJAX 正在运行,但这对示例并不重要)它具有由“边缘”连接的“顶点”的概念。UI 允许您在地图上添加和删除顶点,并启用或禁用顶点对之间的边。
有两种方法可以禁用从顶点 A 到顶点 B 的边:
- 单击边缘,使“边缘详细信息”窗口为您提供“禁用此边缘”按钮;或者
- 单击顶点 A(或 B)以使“顶点详细信息”窗口为您提供附近顶点的清单,您可以从中取消选中顶点 B(或 A)。
以下是 MVC 的底层工作原理(但请参阅这篇文章的末尾以获取更新,我在其中纠正了我理解的问题):
- 模型:顶点对象列表和边对象列表。
- 视图:一个 GMaps UI,带有标记和折线,加上复选框和按钮以及“顶点详细信息”和“边缘详细信息”DIV。
- 控制器:
- 当复选框和按钮上的事件触发时更新模型的 JS 函数;和
- 当模型上的事件触发时更新视图的 JS 函数。
这是具体的不雅:
- 用户将 Vertex Details Window 聚焦在 Vertex A 上,Edge Details Window 聚焦在从 Vertex A 到 Vertex B 的边上。
- 用户在边缘详细信息窗口中单击“禁用此边缘”。
- 控制器函数 1 获取点击事件,并在 Edge 模型对象上调用 disable()。
- Edge 模型对象触发“我刚刚被禁用”事件。
- 控制器功能 2 收到“我刚刚被禁用”事件,并且
- 重新绘制边缘详细信息窗口以显示“我已禁用!” 和
- 在顶点详细信息窗口中取消选中顶点 B。
- 废话!这会再次触发控制器功能 1,它正在侦听意味着边缘被禁用的 UI 事件!
所以有一个不必要的模型的重新更新,以及视图的重新更新。在更复杂的视图中,事件触发事件触发事件,这可能会导致数十个无关更新!
更新:一个很好的答案。
我有点误解了 MVC。如上所述,我不只有一个视图:我有几个视图到几个模型中。特别是,我有一个特定节点的边缘复选框列表视图,以及一个单独的“详细窗口样式”边缘视图。
此外,我不应该让一个控制器函数在模型更改时更新所有视图:每个视图都应该在模型更改时自行修改。
因此,如果每个视图都在模型上注册“状态更新”事件,并且每个视图在收到这些事件后自行更新,那么我的循环事件问题的答案就是:
复选框列表视图将在模型状态更改后更新复选框时禁用复选框事件。
现在,如果用户通过 Edge Detail 窗口禁用 Edge,Controller 会更新 Edge Model,checkbox-list View 会收到更新通知,并且 checkbox-list View 足够聪明,可以在更改状态的同时使复选框事件静音适当的复选框。
这比我原来的解决方案更可口,其中一个控制器更新所有视图——因此必须知道哪些视图需要特别注意和馈送以避免循环。相反,只有带有麻烦的 UI 元素的单个 View 必须处理该问题。
感谢那些回答我问题的人!