在MVC中防止循环事件的优雅方式? [英] Elegant way to prevent circular events in MVC?

查看:105
本文介绍了在MVC中防止循环事件的优雅方式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简而言之:



在MVC中,如何区分复选框点击(或选择框或列表框更改)从人的意义控制器,修改模型,并从控制器中的复选框单击(或选择框或列表框更改)意思是我正在更新视图,因为模型已更改?






示例:



我有一个JS应用程序一个大的HTML + JS页面;它后面有一个服务器,AJAX继续进行,但是这个例子并不重要),它具有由边缘连接的顶点的概念。 UI可以在地图上添加和删除顶点,并启用或禁用顶点对之间的边。



有两种方法可以将边缘从顶点A禁用到顶点B:


  1. 点击边缘,使边缘细节窗口为您提供禁用边缘按钮;或

  2. 点击顶点A(或B),使顶点细节窗口为您提供附近顶点的清单,从中可以取消选中顶点B(或A)。 / li>

这是在MVC()中的工作原理,但是看到这篇文章的最后一个更新,我在哪里纠正问题在我的理解):




  • 模型:顶点对象列表和边缘对象列表。

  • 查看:一个GMaps UI,标记和折线,加上复选框和按钮以及顶点细节和边缘细节DIV。

  • 控制器:


    • 在复选框和按钮上的事件触发时更新模型的JS函数;和

    • 在模型上的事件触发时更新视图的JS函数。




这是具体的无效


  1. 用户具有顶点细节窗口专注于顶点A,边缘细节窗口将边缘从顶点A到顶点B。

  2. 用户点击边缘细节窗口中的禁用边缘。

  3. 控制器功能1获取点击事件,并在Edge模型对象上调用disable()。

  4. Edge模型对象触发我刚刚被禁用事件。

  5. 控制器功能2接收到我刚刚被禁用事件,


    1. 重绘边缘细节窗口说我是残疾人!和

    2. 取消选中顶点细节窗口中的顶点B.


      1. 再次触发控制器功能1,它正在监听UI事件,意味着边缘被禁用!



所以有一个不必要的重新更新的模型,并重新更新视图。在更复杂的视图中,发生事件触发事件的事件,这可以使数十个无关的更新!





更新:一个很好的答案。



我误解了MVC。我没有只有一个视图,如上所述:我对几个模型有几个意见。特别是,我有一个复选框列表对特定节点的边缘视图,以及单独的详细窗口样式边缘视图。



此外,我当模型更改时,不应该有一个控制器功能更新所有视图:当模型更改时,每个视图应修改本身



查看模型上的状态更新事件的注册表,每个视图在收到这些事件后自动更新,然后我的循环事件问题的答案就是这样:



复选框列表视图将在模式状态更改后更新复选框的时候禁用复选框事件。



现在如果用户通过边缘细节窗口禁用边缘,控制器更新边缘模型,复选框列表视图接收更新的通知,并且复选框列表视图很聪明,可以在更改相应复选框的状态时静默复选框事件。 / p>

这比我原来的解决方案更可口,一个控制器更新所有视图,因此必须知道哪些视图需要特别注意和馈送才能避免循环。相反,只有具有麻烦的UI元素的单个视图必须处理该问题。



感谢那些回答我问题的人!

解决方案

回顾一下MVC模型。视图通常应该更新。以下是它的工作原理:控制器更改模型的状态,模型将更新发送到其视图,视图从模型中拉入新状态并进行更新。虽然控制器和视图通常是捆绑的(即,以图形表示方式钻取数据),但是它们绝对不能直接通过模型进行交互。这一般当然是。



所以更新视图的JS函数实际上不是控制器,这是一个重要的区别。它们应该被视为您的观点的一部分。这可能对于手头的问题可能没有帮助,但我认为值得指出。



你也可以不删除你的模型,我想你的意思是你删除某个 您的模型,因为没有任何视图或控制器实际上可以存在(或处于功能状态),如果它们不由模型支持。



不是一个JS代码的骑师,没有使用过gmaps我真的不明白问题所在。更改复选框(checked属性)的状态是否触发onClick()事件?它真的不应该是IMHO,但也许他们实现了这一点,否则你可以把你的控制器附加到onClick()并添加一些逻辑到复选框(或者这是JS,在一个函数中)来更改复选框状态。如果这不可能,选项1和2绝对是你最好的选择。



另外:用户与视图交互



<那么当用户想要与视图交互时会发生什么?通常,小部件将包括视图和控制器。一个复选框有一个视图(您可以看到它是否被检查)以及控制器(您可以单击它)。当您点击复选框时,原则上应该发生以下情况:




  • 复选框控制器收到事件

  • 复选框控制器更改模型中复选框所代表的值的状态

  • 模型更新侦听器(包括复选框)

  • 复选框将其外观更新为反映出该值已经改变了



第一步,控制器如何接收事件有些依赖于语言,但是在OOP语言中附加到这个特定小部件上的用户界面事件的侦听器对象,或者是控制器或通知控制器用户交互。


The question, in brief:

In MVC, how do you distinguish between a checkbox click (or a selectbox or listbox change) from a human meaning "Controller, modify the model", and a checkbox click (or a selectbox or listbox change) from the Controller meaning "I'm updating the view because the model has changed"?


The example:

I have a JS app (all one big HTML+JS page; there's a server behind it, and AJAX going on, but it's not important to the example) which has the notion of "Vertices" connected by "Edges". The UI lets you add and remove Vertices on a map, and enable or disable Edges between pairs of Vertices.

There are two ways to disable an Edge from Vertex A to Vertex B:

  1. click on the Edge to make the "Edge Details" window provide you with a "Disable This Edge" button; or
  2. click on Vertex A (or B) to make the "Vertex Details" window provide you with a checklist of nearby Vertices, from which you can uncheck Vertex B (or A).

Here's how this works under the hood in MVC (but see the end of this post for an update, where I correct problems in my understanding):

  • Model: a list of Vertex objects and a list of Edge objects.
  • View: a GMaps UI, with markers and polylines, plus checkboxes and buttons and "Vertex Details" and "Edge Details" DIVs.
  • Controller:
    • JS functions that update the model when events on the checkboxes and buttons fire; and
    • JS functions that update the view when events on the models fire.

Here's the specific inelegance:

  1. The user has the Vertex Details Window focused on Vertex A, and the Edge Details Window focused on the Edge from Vertex A to Vertex B.
  2. The user clicks "Disable This Edge" in the Edge Details window.
  3. Controller function 1 gets the click event, and calls disable() on the Edge model object.
  4. The Edge model object fires the "I just got disabled" event.
  5. Controller function 2 receives the "I just got disabled" event, and

    1. redraws the Edge Details Window to say "I'm disabled!" and
    2. unchecks Vertex B in the Vertex Details Window.

      1. Crap! This fires Controller function 1 again, which was listening for UI events that mean an edge was disabled!

So there's an unnecessary re-update of the Model, and re-update of the View. In a more complex view with events that fire events that fire events, this can make for dozens of extraneous updates!


Update: a great answer.

I misunderstood MVC a bit. I don't have just one View, as I described above: I have several Views into several Models. In particular, I have a checkbox-list View of Edges to a particular Node, and a separate, "detailed window-style" View of an Edge.

Furthermore, I shouldn't have one controller function updating all views when the Model changes: each View should modify itself when the Model changes.

So if each View registers for "state updated" events on the Model, and each View updates itself upon receipt of those events, then the answer to my circular events question is simply this:

The checkbox-list View will disable checkbox events for the moment that it is updating the checkboxes after a Model state change.

Now if a user disables an Edge via the Edge Detail window, the Controller updates the Edge Model, the checkbox-list View receives notification of the update, and the checkbox-list View is smart enough to silence checkbox events while changing the status of the appropriate checkbox.

This is much more palatable than my original solution, where one Controller updates ALL Views -- and thus has to know which views need special care and feeding to avoid loops. Instead, only the single View with troublesome UI elements has to deal with the problem.

Thanks to those who answered my question!

解决方案

Just to recap the MVC model. Views should generally update themselves. Here's how it works: a controller changes the state of the model, the model sends updates to its views, the views pull in new state from the model and update themselves. While controllers and views are generally bundled (i.e. drilling down on data in a graphic representation) they should never interact directly, only through the model. This in general of course.

So the JS functions that update your views are not actually controllers, which is an important distinction. They should be considered part of your view. This might not be helpful to the problem at hand but I thought it merited pointing out.

You can also not delete your model, I assume you mean you're deleting someting from your model, since no views or controllers can actually exist (or be in a functional state) if they're not backed by a model.

Not being a JS code jockey and not having used gmaps I don't really see where the problem is. Does changing the state of a checkbox(checked property) fire the onClick() event? It really shouldn't IMHO but perhaps they implemented it that way, otherwise you could just attach your controller to the onClick() and add some logic to the checkbox (or, this being JS, in a function somewhere) to change the checkbox state. If that's not possible, option 1 and 2 are definitely your best bet.

addition: user interacting with a view

So what happens when a user wants to interact with a view? Frequently a widget will include both a view and the controller. A checkbox has a view (you can see if it's checked or not) and also a controller (you can click it). When you click the checkbox, in principle the following should happen:

  • checkbox controller receives the event
  • checkbox controller changes the state for the value this checkbox represents in the model
  • model updates listeners (including the checkbox)
  • checkbox updates its look to reflect that that value has changed

The first step, how the controller receives the event is somewhat language dependent, but in OOP languages it's likely a listener object attached to user interface events on this particular widget which either is the controller or notifies the controller of the user interaction.

这篇关于在MVC中防止循环事件的优雅方式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆