【问题标题】:MVC-like UI updates in Javascript/jQuery: best practices?Javascript/jQuery 中类似 MVC 的 UI 更新:最佳实践?
【发布时间】:2009-02-24 09:12:44
【问题描述】:

我遇到了一个尴尬的问题。我有一个网页,上面有很多按钮,需要在不同的地方禁用和启用。现在,如果这是一个 Swing(或任何其他桌面 UI 界面),那将非常简单:我只需为我感兴趣的模型更改添加侦听器并相应地更新 UI。

这真的是基本的 MVC 东西。

问题是,对于如何在 Javascript 中很好地处理这个问题,我有点茫然。我正在走一条路线,最终会得到一些真正的意大利面条代码,其中按钮的点击侦听器正在更新 UI 控件,但结果不会很好。

编辑:让我给你一个更具体的例子。

示例

想象一个列出未结订单的屏幕。这些订单显示在表格中,因为每一行(订单)都有多个属性,例如当前管理订单的人员、下订单的人员、订单的用途、下订单的时间和订单的状态。

我已经完成了,因此您可以通过单击行来选择这些订单中的一个(或多个)。这会添加一个“selected”类,它会更改样式,很像列表。

关于行为,如果用户选择一个订单,则某些操作变为可用,例如打开订单(查看详细信息)、获得所有权、取消等。订单的属性也可能影响可用的操作,例如,如果订单已经为其他人“拥有”,则某些操作将被禁用。

如果您选择了多个订单,则其中一些选项(例如打开订单)不可用。

此外,通过后台 Ajax 调用,列表会定期刷新新订单。用户还可以单击刷新或过滤订单(按名称、日期范围等),然后重新加载订单。在重新加载订单时,某些按钮会被禁用。

我打算做第二个例子,但我认为这个例子足够复杂,足以说明问题的类型。现在我通过提供各种控件类开始了这一点。例如,当一个项目被选中时,具有“select”类的元素可能会被禁用/启用/设置样式。

现在这在简单的情况下工作得相当好,但我遇到了控件状态取决于多个条件的问题。此外,这些类也因某些元素想要设置样式、某些控件想要被禁用/启用以及在某些情况下两者都需要发生的事情而分崩离析。

在 Swing 中,我倾向于通过一种 updateUI() 方法来处理这类事情,只要相关控件或模型的状态发生更改,就会调用该方法。然后它将显式设置所有控件的状态。现在这可以说不是最有效的方法(例如,如果您有 30 个控件并且只需要更新其中一个,这有点浪费),但我发现这种简单性是值得的。另一种选择是控件/模型最终获得了太多关于它们所依赖的控件或依赖于它们的控件的信息。从耦合的角度来看,它变得很混乱。

但我在 Javascript 中没有这种(明显的)机制。 jQuery 提倡的不显眼的 Javascript 非常棒,因为它可以阻止随机代码 sn-ps 在您的代码中乱扔垃圾。但我需要更进一步,有一些方法来管理它的复杂性(因为它是一个相当复杂的屏幕,只会变得更复杂)。

【问题讨论】:

    标签: javascript jquery model-view-controller


    【解决方案1】:

    如果您想保持理智,请使用状态机。

    您并没有真正提供有关您的 UI 功能的详细信息,因此我将举一个示例。假设您有一个文件上传页面。用户应该能够选择一个文件,单击一个上传按钮,然后在上传完成后返回到他们来自的页面。所以你可以有三种状态,“SelectFile”、“Uploading”、“Finished”。在“SelectFile”状态下,应启用控件以允许用户选择文件。在“上传”状态下,这些控件应该被禁用,并且用户应该看到一个进度指示器。在“完成”状态下,用户应该被重定向。

    当然,听起来您的情况更复杂,但同样的想法也适用。如果用户界面的某些部分进行交互,您可能需要多个状态机。没关系。

    当您想更改用户界面上启用/禁用的元素时,您只需更改状态机的状态。状态机本身告诉各种用户界面控件根据当前状态更新自己。您可以使用 Bharani 的(好的,赞成的)建议使用类来执行此操作。或者任何适合你的机制。

    好消息是控件不再相互交互。它们只与状态机交互。因此,您可以摆脱所有状态反弹不正确或无休止地递归的情况。

    【讨论】:

    • 我最近一直在用 javascript 做一些 UI,这些 UI 非常脆弱且难以更改。他们似乎急于被建模为状态机,所以这可能是我未来基于 js 的 ui 的起点。
    【解决方案2】:

    为 div 分配特定的类名。这样,即使它们在功能上重叠,您也可以简单地继续向 div 添加类名,并且由于 jquery 的链性质,所有注册的事件处理程序都将被执行。

    为了在 ajax 调用期间控制表单元素 - 您可以添加 ajaxStart 和 ajaxEnd,或者您可以使用 ajaxComplete 并在回调中处理所有代码。

    【讨论】:

    • 我相信这个解决方案正是对@cletus 的恐惧。这导致意大利面条代码。除非我不明白(这意味着你可能想澄清一下)。
    【解决方案3】:

    我想我明白了你的问题。我以前在这样的屏幕上工作过,我总是最终重构以更好地构建代码。但有时,如果您可以重新组织功能本身,这样您就不必在一个地方处理所有事情,这会更容易。我认为 GUI 也应该被视为一种功能 - 做好一件事,做好一件事。

    【讨论】:

      【解决方案4】:

      我认为数据建模对于 JavaScript 应用程序很重要。我正在为医疗诊所做这个调度项目,我有一个 JSON 数据结构,可以为办公室的椅子/病人建模。当模型中的业务逻辑发生变化时,Ember 会自动更新视图(UI 小部件)。所以马上就消除了很多 sphagetti 代码。如果你正在做一些图形化的用户交互,那么不使用现有的 MVC 模式或创建自己的 MVC JS 类几乎是一种犯罪。结构化的纪律起初并不受欢迎,但当您稍后看到它如何降低血压并使维护变得更加愉快时,这是值得的。如果它们很小,我不会将它用于简单的一次性项目。它更适合中等复杂性或高级复杂性。任何需要我超过一周的时间我都会使用 Ember。我用过 knockout.js 和 Angular,我真的很喜欢 Ember 的 Handlebars 模板语法。眼睛好,效率高。

      【讨论】:

        猜你喜欢
        • 2013-11-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-04
        • 2021-11-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多