【问题标题】:JavaScript - Clientside separation of Model and ViewModel?JavaScript - 模型和视图模型的客户端分离?
【发布时间】:2016-11-28 20:28:56
【问题描述】:

我在另一个网站上already asked this question,但由于它几乎没有引起任何关注(更不用说答案),我希望它可能适合这里。

我正在使用带有 Knockout.js 的 Model-View-ViewModel 方法开发 Web 应用程序。在阅读了 John Gossman 的 original introduction of MVVM 之后,我意识到我的 ViewModel 始终包含应用程序的所有逻辑,不仅是 UI 逻辑,而是所有内容。

我在某处读到,使用 Knockout,模型被认为是数据库,或者通常是服务器上的数据。但根据 MVC,该模型还包含对数据进行一些处理且与 UI 无关的函数。

所以我想知道拥有一个独立于 ViewModel 对象的单独模型对象是否合理?这背后的想法是 ViewModel 将仅包含 UI 逻辑(如 Gossman 所期望的那样),而 Model 将仅包含业务逻辑(如在 MVC 中),这与实际 View 无关。示例:

var viewModel = {
    hint: ko.observable("idle"), //text visible in the View
    buttonClicked: function () {
        this.hint("doing stuff");
        model.doStuff();
        this.hint("done");
    }
};

var model = {
    doStuff: function () {
        //business logic, UI independent
    }
};

是否有可以从 MVVM 模式定义中得出的建议或“最佳实践”?

【问题讨论】:

  • 我不知道它是否被认为是最佳实践,或者它是否源自任何模式,但您描述的这种“架构”非常方便,尤其是在大型项目中,因为模型本身的逻辑只为模型做特定的功能,可以在多个视图模型中重复使用,用于不同的目的。分离模型和视图模型的逻辑肯定没有坏处
  • 对我来说这不是最佳实践,它几乎是一个要求。当您的逻辑变得复杂时,如果您不拆分业务逻辑和 UI 逻辑,您的视图模型就会变得不可读。此外,它使错误管理更容易,因为它分离了层

标签: javascript model-view-controller mvvm knockout.js


【解决方案1】:

我认为尝试将纯数据模型与 viewModel 分开会有点模糊,因为 ViewModel 可以包含“派生”列,这样会模糊“模型”与“viewModel”中视图需要的内容之间的界限'

我通常使用类(忘记你是如何分类的)来封装从真正的服务器端模型到我的视图将使用的视图模型的转换......包括派生列(例如 FullName = FirstName + ' ' + LastName)、数据转换(例如日期格式)以及我为操作 viewModel 提供的函数。

实际上,您最终会拥有嵌套的(每个类本身就是一个“viewModel”)来封装复杂的实体,并将转换/函数与它们关联的实体组织在一起。请注意,操作数组的函数的附加层比它们修改的集合中的实体高一级。

所以书籍视图模型可能看起来像:

MainVM:
  Authors: observableArray
  AddAuthor: function
  RemoveAuthor: function

Author class: 
  FirstName
  LastName
  FullName: (derived)
  Books: observableArray
  AddBook: function
  RemoveBook: function

Book class: 
  Title
  ISBN
  PublishDate (function to format raw date)

此外,UI 逻辑(例如,处理 DOM 或 Jquery 的任何东西)不属于这里的任何地方......但在自定义 bindingHandlers 或淘汰赛扩展中。

【讨论】:

    【解决方案2】:

    我发现将 Knockout 巧妙地划分为规范和实现会更有帮助。 HTML 文件在外观和行为方面完全指定了应用程序。绑定指定了一个接口,您必须实现该接口才能使应用程序正常工作。

    JavaScript 方面的一切——你的视图模型和任何自定义绑定,以及任何底层代码——都是关于实现指定的接口。如何分解任务完全是一个实现细节。良好的编程实践表明,如果您有可以在多个地方使用的例程,特别是如果它们可能在其他项目中有用,那么您应该为它们创建一个库。这似乎普遍适用于业务逻辑。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-09
      • 1970-01-01
      • 1970-01-01
      • 2013-11-09
      相关资源
      最近更新 更多