JavaScript MVVM模式 您所在的位置:网站首页 mvvm模式和mvc的实现 JavaScript MVVM模式

JavaScript MVVM模式

2023-08-11 07:28| 来源: 网络整理| 查看: 265

MVVM

MVVM(Model View ViewModel)是一种基于MVC和MVP的架构模式,它试图将用户界面(UI)从业务逻辑和行为中更加清晰地分离出来。为了这个目的,很多例子使用声明变量绑定来把View层的工作从其他层分离出来。

这促进了UI和开发工作在同一代码库中的同步进行。UI开发者用他们的文档标记(HTML)绑定到ViewModel,在这个地方Model和ViewModel由负责逻辑的开发人员维护。

历史

MVVM(如其大名)最初是由微软定义,用于Windows Presentation Foundation(WPF)和Silverlight,在John Grossman2005年的一篇关于Avalon(WPF的代号)的博文中被官方推出。它也作为方便使用MVC的一种可选方案,为Adobe Flex社区积累了一些用户量。

先于微软采用的MVVM名称,在社区中已经有了一场由MVC像MVPM迁移的运动:模型-视图-展现模型。Marton Fowler在2004年为那些对此感兴趣的人写了一篇关于展现模型的文章。展现模型的理念的内容要远远长于这篇文章,然而这篇文章被认为是这一理念的重大突破,并且极大的捧红了它。

在微软推出作为MVPM的可选方案的MVVM后,就出现了许多沸沸扬扬的“alt.net”圈子。其中许多声称这个公司在GUI世界的霸主地位给与了它们将社区统一为整体的机会,出于市场营销的目的,按照它们所高兴的方式对已有的概念重新命名。一个进步的群体也承认MVVM和MVPM其实实在是同样的概念,只是展现出来的是不同的包而已。

在近几年,MVVM已经在Javascript中得到了实现,其构造框架的形式诸如KnockoutJS,Kendo MVVM和Knockback.js,获得了整个社区的积极响应。

现在就让我们来看看组成了MVVM的这三个组件。

模型

和其它MV*家族成员一样,MVVM中的模型代表我们的应用用到的领域相关的数据或者信息。一个领域相关的数据的典型例子是用户账号(例如名字,头像,电子邮件)或者音乐唱片(例如唱片名,年代,专辑)。

模型持有信息,但是通常没有操作行为。它们不会格式化信息,也不会影响数据在浏览器中的表现,因为这些不是模型的责任。相反,数据格式化是由视图层处理的,尽管这种行为被认为是业务逻辑,这个逻辑应该被另外一个层封装,这个层和模型交互,这个曾就是视图模型。

这个规则唯一的例外是验证,由模型进行数据验证是被认为可以接受的,这些数据用于定义或者更新现存的模型(例如输入的电子邮件地址是否满足特定的正则表达式要求?)。

在KnockoutJS中,模型遵从上面的定义,但是通常对服务端服务的Ajax调用被做成即可以读取也可以写入模型数据。

如果我们正在构建一个简单的Todo应用,使用KnockoutJS模型来表示一个Todo条目,看起来像下面这个样子:

var Todo = function ( content, done ) { this.content = ko.observable(content); this.done = ko.observable(done); this.editing = ko.observable(false); };

注意:在上面小段代码里面,你可能发现了,我们在KnockoutJS的名字空间里面调用observable()方法。在KnockoutJS中,观察者是一类特殊的JavaScript对象,可以将变化通知给订阅者,并且自动检测依赖关系。这个特性使我们在模型值修改之后,可以同步模型和视图模型。

视图

使用MVC,视图是应用程序中用户真正与之打交道的唯一一个部分.它们是展现一个视图模型状态的一个可交互UI.此种意义而言,视图是主动的而不是被动的,而这也是真正的MVC和MVP的观点.在MVC,MVP和MVVM中视图也可以是被动的,而这又是什么意思呢?

被动视图仅仅只输出要展示的东西,而不去接受任何用户的输入。

这样一个视图在我们的应用程序中可能也没有真正的模型的概念,而可以被一个代理控制.MVVM的主动视图包含数据绑定,事件和需要能够理解视图模型的行为.尽管这些行为能够被映射到属性,视图仍然处理这来自视图模型的事件。

记住视图在这里并不负责处理状态时很重要的——它使得其与视图模型得以同步。

KnockoutJS视图是简单的一个带有声明链接到视图模型的HTML文档。KnockoutJS视图展示来自视图模型的信息,并且传递命令给他(比如,用户在一个元素上面点击),并且针对视图模型的变化更新状态。而使用来自视图模型的数据来生成标记的模板也能够被用在这个目的上。

未来给出一个简单的初始示例,我们可以看看Javascritpt的MVVM框架KnockoutJS,看它如何允许一个视图模型的定义,还有它在标记中的相关绑定。

视图模型:

var aViewModel = { contactName: ko.observable("John") }; ko.applyBindings(aViewModel);

视图:

You have a really long name!

Contact name:

我们的text-box输入(源)从contactName获取它的初始值,无论何时contactName发生了改变都会自动更新这个值.由于数据绑定是双向的,像text-box中输入也将据此更新contactName,以此保持值总是同步的。

尽管这个实现特定于KnockoutJS,但是包含着"You have a really long name!"文本的

标签包含有简单的验证(同样是以数据绑定的形式呈现)。如果输入超过10个字符,这个标签就会显示,否则保持隐藏。

让我们看看一个更高级的例子,我们可以看看我们的Todo应用。一个用于这个应用的裁剪后的KnockoutJS的视图,包含有所有必要的数据绑定,这个视图看起来是下面这个样子。

Todos Mark all as complete

Nei Kerkin 已经使用上面的方式组合成了一个完整的TodoMVC示例,它可以 从 这里获取到。 虽然上面的解释看起来像是有许多的工作要做,现在我们就有一个一般的getBindingmethod方法要写。比起为了编写我们的KnockoutJS应用程序而严格使用数据绑定,简单的重用和使用数据类更加的琐碎。最终的结果是希望得到一个干净的标记,其中我们的数据绑定会从视图切换到一个绑定对象。

MVC VS MVP VS MVVM

MVP和MVVM都是MVC的衍生物。它和它的衍生物之间关键的不同之处在于每一层对于其它层的依赖,以及它们相互之间是如何紧密结合在一起的。

在MVC中,视图位于我们架构的顶部,其背后是控制器。模型在控制器后面,而因此我们的视图了解得到我们的控制器,而控制器了解得到模型。这里,我们的视图有对模型的直接访问。然而将整个模型完全暴露给视图可能会有安全和性能损失,这取决于我们应用程序的复杂性。MVVM则尝试去避免这些问题。

在MVP中,控制器的角色被代理器所取代,代理器和视图处于同样的地位,视图和模型的事件都被它侦听着并且接受它的调解。不同于MVVM,没有一个将视图绑定到视图模型的机制,因此我们转而依赖于每一个视图都实现一个允许代理器同视图去交互的接口。

MVVM进一步允许我们创建一个模型的特定视图子集,包含了状态和逻辑信息,避免了将模型完全暴露给视图的必要。不同于MVP的代理器,视图模型并不需要去引用一个视图。视图可以绑定到视图模型的属性上面,视图模型则去将包含在模型中的数据暴露给视图。像我们所提到过的,对视图的抽象意味着其背后的代码需要较少的逻辑。

对此的副作用之一就是视图模型和视图层之间新增的的用于翻译解释的一层会有性能损失。这种解释层的复杂度根据情况也会有所差异——它可能像复制数据一样简单,也可能会像我们希望用视图理解的一种形式去操作它们,那样复杂。由于整个模型是现成可用的,从而这种操作可以被避免掉,所以MVC没有这种问题。

Backbone.js Vs KnockoutJS

了解MVC,MVP和MVVM之间的细微差别是很重要的,然而基于我们已经了解到的东西,开发者最终会问到是否它们应该考虑使用KnockoutJS而不是Backbone这个问题。下面的一些相关事项对此可能有些帮助:

两个库都设计用于不同的目标,它常常不仅仅简单的知识选择MVC或者MVVM的问题。 如果数据绑定和双向通信是你主要关注的问题,KnockoutJS绝对是应该选择的方式。实践中任何存储在DOM节点中的值或者属性都能够使用此方法映射到Javascript对象上面。 Backbone在同RESTful服务的易于整合方面有其过人之处,而KnockoutJS模型就是简单的Javascript对象,而更新模型所需要的代码也必须要由开发者自己来写。 KnockoutJS专注于自动的UI绑定,如果尝试使用Backbone来做的话则会要求更加细节的自定义代码。由于Backbone自身就意在独立于UI而存在,所以这并不是它的问题。然而Knockback也确实能协助并解决此问题。 使用KnockoutJS,我们能够将我们自己拥有的函数绑定到视图模型观察者上面,任何时候观察者一旦发生了变化,它都会执行。这允许我们能够拥有同在Backbone中发现的一样级别的灵活性。 Backbone内置有一个坚实的路由解决方案,而KnockoutJS则没有提供路由供我们选择。然而人们如果需要的话,可以很容易的加入这个行为,使用Ben Alman的BBQ插件或者一个像Miller Medeiros优秀的Crossroads就行了。

总结下来,我个人发觉KnockoutJS更适合于小型的应用,而Backbone的特性在任何东西都是无序的场景下面才会是亮点。那就是说,许多开发者两个框架都已经使用过来编写不同复杂度的应用程序,而我建议在一个小范围内两种都尝试一下,在你决定哪一种能更好的为你工作之前。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有