我正在尝试实现一个基于MVVM的单页应用程序,目前正在使用框架Knockout.js来处理MVVM的视图模型/视图部分。不过,我很困惑,因为我所看过的实现Knockout的每个例子都涉及到将整个视图模型保存到数据库中。这些例子不是缺少一个“模型”步骤吗?在这个步骤中,视图模型与数据层模型同步,并且模型进行验证/服务器同步。
我希望在单个页面上有多个不同的模板/视图,每个模板/视图具有不同的视图模型。我发现knockout.js缺少的另一件事是在不同视图之间同步单个模型(而不是视图模型)。我不认为有一个每个视图共享的巨型视图模型是有意义的,所以我认为每个视图都有自己的视图模型,但是每个视图模型将与每个视图所需的几个应用程序范围的模型的字段同步。
我正在处理的页面获取一个巨大的模型(30+字段、多个父/子关系层),我认为让所有视图模型与此模型同步是有意义的。我已经研究过Knockback.js (它结合了knockout.js和backbone.js),但是我最终重写了大多数函数,如fetch、set、save,因为页面是从API获取数据(而且我不能只是来回同步整个模型和服务器),所以我决定不使用它。
我的应用程序的可视化示例:
(模型层)M=M
(视图模型/视图层)
另一个例子
一个示例模型是User = {firstName:"first",lastName:"last",.}
一个视图模型只需要名字,另一个视图模型只需要姓。
ViewModelA={firstName: app.User.firstName()}
ViewModelB={firstName: app.User.lastName()}
这是为模型和视图模型更改定义发布/子系统的唯一方法吗?这是一个好的/可维护的体系结构吗?我是不是漏掉了一个基本概念?欢迎所有建议。
发布于 2012-06-28 20:10:12
如果我没看错,这里有很多问题都集中在如何用Knockout构建一个MVVM / SPA。正如你所指出的,有几件事要处理。一个是如何在视图模型/视图对之间进行通信。
Master ViewModel的一种方法是有一个主视图模型作为@Tyrsius的答案。您的shell可以有一个视图模型来绑定更多可用数据。主视图模型也可以编排子视图模型。如果您走这个路线,那么您必须小心地将外壳绑定到主视图模型,并将内部外壳绑定到DOM中的特定HTML元素。如果需要的话,主视图模型可以方便它们之间的通信。
解耦的视图/视图对另一种选择是使用视图模型/视图对,而不使用主视图模型。每个视图都被加载到DOM的一个区域中,并自行绑定。它们作为一个独立的单元,彼此解耦。您可以使用pub/sub进行对话,但是如果您所需要的只是通过可观测数据同步的方法,那么Knockout提供了许多选项。我喜欢的是每个视图模型表面模型对象。因此,视图有一个视图模型,它将特定于视图的数据(来自模型)表面显示出来。因此许多视图模型可能以不同的方式出现在相同的模型上。因此,当视图更新viewmodel属性(即模型中的视图)时,它会波及到使用相同模型的任何其他加载视图模型。
datacontext 更进一步,您可以创建一个数据文本模块来管理模型中的数据。您将询问模型的数据文本(例如:客户列表),并检查数据文本是否已经启动,如果没有,则从ajax调用中获取数据文本。无论哪种方式,都是从视图模型和模型中抽象出来的。数据文本获取数据并将模型返回到视图模型。这样您就可以非常解耦,但是您可以通过数据文本共享数据(模型)。
我可以继续下去..。但是如果这是在回答你的问题,请告诉我。如果没有,很乐意回答任何其他细节。
**免责声明:我正在SPA上建立一个Pluralsight课程(使用Knockout和这个策略) :-)
发布于 2012-06-28 18:50:36
这是一个受欢迎的兴趣领域,所以我希望你会得到一些更好的答案,但现在开始。
模型
是的,您绝对应该有数据的服务器端表示,这就是您的模型。这取决于您的服务器和数据库。对于MVC3,这是您的实体模型。对于Django或Ruby,您将定义db模型作为db设置的一部分。这部分取决于你的具体技术。但是,agian,,,您应该有一个模型,并且服务器绝对应该执行数据验证。
应用程序(ViewModel)
建议您的视图都有自己的视图模型。您的页面也可以有一个视图模型,如果您愿意的话,一个,它可以跟踪所有这些视图。如果您采用这种方式,应用视图模型应该负责在视图之间切换,并实现任何其他应用程序级别的逻辑(比如散列式导航,另一种流行的单页工具)。这个层次结构非常重要,但并不总是简单的。这将取决于您的应用程序的具体需求。您不仅限于一个平面视图模型。这不是唯一可行的方法。
特别例子:
var ThingViewModel = function(name, data){
this.name = ko.observable(name);
//Additional viewmodel stuffs
};
var AppViewModel = function(initialData){
//Process initial data
this.thing = new ThingViewModel(someName, someData);
};我现在正在做一个类似的项目,纯粹是为了学习(而不是一个现实世界的应用程序),这是托管的在GitHub上,如果你想看看一些真正的例子的话。注意,目前dev分支远远领先于master分支。我确信它包含了一些不好的模式(尽管指出它们,我也在学习),但您可能会从中学到一些东西。
发布于 2012-06-29 04:46:17
我有一个类似的复杂解决方案,在这个解决方案中,我正在将一个WPF应用程序重新加工成一个web版本。WPF版本处理复杂的域对象,它通过演示器模型绑定到视图。
在web版本中,我实现了一些简化的服务器端视图模型,这些模型使用Automapper在域对象之间来回转换。然后,这些服务器端视图模型以JSON的形式来回发送到客户端,并使用映射插件映射到相应的Knockout视图模型(实例化函数,每个函数负责创建具有子映射选项的子函数)。
当我需要保存/验证我的UI时,我将我的全部或部分Knockout视图模型映射回一个普通Javascript对象,将其作为JSON发布,MVC框架将其绑定回服务器端视图模型,这些将自动返回到域对象,验证并可能由我们的域层更新,然后返回并重新映射修改后的完整或部分图。
目前,我只有一个主页面进行淘汰赛操作,但我和您一样,也会有多个上下文,需要处理相同的模型(我的域对象),而不同的视图模型则取决于我对它们的处理方式。
我已经构建了服务器端视图模型目录等等,以及我的Knockout视图模型的结构。到目前为止,这种方法运行良好。希望这能有所帮助。
https://stackoverflow.com/questions/11250075
复制相似问题