背景:MVC是一种架构设计模式,鼓励通过关注点分离改进应用程序组织。过去,MVC被广泛用于构建桌面和服务器端应用程序。如今,Web应用的开发越来越接近于传统的应用软件开发,Web与应用的界限进一步模糊。传统编程语言中的设计模式也慢慢融入到Web前端开发中。由于前端开发的环境特点,从经典的MVC模式衍生出很多MV*模式,在各种Javascript框架中实现了多少演变。在研究MV*模式和各种框架的过程中,是“剪不断,推理依旧乱”:为什么不同地方说的MVC不一样?MVP和MVVM的出现是为了解决什么问题?据说“Web前端开发中根本不能用MVC”?翻了一大堆资料,十万个理由,不过貌似view,model,controller,decoupling,monitor,notification,active,passive,registration,bindingdefinition,rendering等各种名词的排列组合好像汪峰的歌词。本文希望以通俗易懂的方式理清一些关系。因接触时间有限,英文阅读能力有限,难免会有误会。欢迎讨论和指正。MVC蜕变MVC历史MVC最初是在研究Smalltalk-80(1979)期间设计的。恐怕没有一本书能回到计算机石器时代来介绍Smalltalk代码是如何实现MVC的。当时的应用场景很难知道,这一切都要追溯到80后出生之前。但当时的图形界面非常少,施乐正在开发一种用户友好的图形界面,以取代远在千里之外的电脑屏幕上的命令行和DOS提示符。那时候的计算机世界是混乱的、综合的,然后出现了造物主,他把现实世界从模型中抽象出来形成模型,把人机交互从应用逻辑中分离出来形成视图,然后就有了空气、水、鸡肉、鸡蛋什么的。《设计模式:可复用面向对象软件的基础》发表于1995年,对MVC进行了深入的讲解,对其使用起到了重要的推广作用。MVC包括三种类型的对象,将它们分开以提高灵活性和可重用性。模型模型用于封装与应用程序业务逻辑相关的数据和数据的处理方法。将有一个或多个视图收听此模型。一旦模型的数据发生变化,模型会通知相关的视图。视图是描述模型当前状态的屏幕表示。当模型的数据发生变化时,视图有机会相应地刷新自己。控制器定义了用户界面如何响应用户输入,在不同层次之间起到组织作用,并用于控制应用程序的流程。它处理用户行为和数据模型的变化。经典MVC模式实线:方法调用虚线:事件通知涉及到两个设计模式:view和model之间的观察者模式,view观察model,提前注册到这个model上,让view知道datamodel上发生了什么变化.视图和控制器之间的策略模式策略是表示算法的对象。MVC允许在不改变视图外观的情况下改变视图响应用户输入的方式。例如,您可能希望更改视图对键盘的响应方式,或者使用弹出菜单而不是命令键。MVC将响应机制封装在控制器对象中。有一个控制器类层次结构,可以通过对现有控制器进行适当更改来轻松创建新控制器。视图使用控制器子类的实例来实现特定的响应策略。要实现不同的响应策略,只需将它们替换为不同类型的控制器实例即可。您甚至可以通过更改视图的控制器来更改视图在运行时响应用户输入的方式。例如,可以通过简单地为视图提供一个忽略输入事件的控制器来禁止视图接受任何输入。好了,如果你被以上言论搞糊涂了,请继续往下看《设计模式:可复用面向对象软件的基础》。MVCforJAVASCRIPT我们回顾了经典的MVC,接下来要说的MVC主要是用Javascript实现的。javascriptMVC模式的源码图如图所示。视图承担了控制器的部分功能,负责处理用户输入,但不需要知道下一步要做什么。它依靠控制器为她做出决定或处理用户事件。事实上,前端视图已经具备独立处理用户事件的能力。如果每个事件都要流经控制器,势必会增加复杂度。同时,视图也可以委托控制器处理模型的变化。模型数据发生变化后,通知视图更新显示给用户。这个过程是一个循环,一个循环的过程。这种从经典MVC到JavascriptMVC的1对1转换让控制器的角色有点尴尬。MVC这种结构的正确性在于,任何界面都需要面向用户,而控制器“是连接用户和系统的纽带”。在经典的MVC中,控制器要做的大部分事情是将用户输入分发到不同的视图,并在必要时从视图中获取用户输入以更改模型。在Web和目前的大部分UI系统中,控制器的职责已经由系统来实现。由于某种原因,控制器和视图之间的分界线越来越模糊。也有人认为视图启动action时应该将视图归于控制器。例如在Backbone中,Backbone.View和Backbone.Router一起承担了控制器的职责。这为MVC中控制器的发展铺平了道路。MVPMVP(model-view-Presenter)是经典MVC设计模式的衍生,由Taligent在1990年代创立,是C++CommonPoint的典范。后台不再研究,看上图就知道和MVC的区别了。在MVP模式经典MVC中,捆绑了一对控制器视图来表示一个ui组件。controller直接接受用户输入并将输入转化为相应的命令来调用模型的接口,修改模型的状态,最后通过观察者模式重新渲染视图。进化成MVP的切入点是修改controller-view的绑定关系。为了解决controller-view的绑定关系,会进行改造,让view既有UI组件的结构,又有处理用户事件的能力,让controller可以独立出来。为了统一管理用户事件,view只负责将用户产生的事件传递给controller,由controller统一处理。这样做的好处是多个视图可以共享同一个控制器。这时候controller也已经从组件级别提升到应用级别,但是更新view的方式还是和经典的MVC一样:通过Presenter更新model,通过observer模式更新view.还有一个明显的区别就是MVC是一个循环,一个循环的过程,而MVP不是,依靠Presenter为核心,负责从模型中取出数据填充到视图中。MVP常见的实现方式是被动视图(passiveview)。Presenter观察模型而不是视图观察模型。一旦模型改变,视图将被更新。Presenter有效地将模型绑定到视图。视图公开setter接口,以便Presenter可以设置数据。使用这种被动视图结构,没有直接数据绑定的概念。但它的好处是直接在视图和模型之间提供更清晰的分离。但是缺少数据绑定支持意味着您必须单独专注于一项任务。在MVP中,应用的逻辑主要在Presenter中实现,其中view是一个很薄的层。MVVMMVVM,Model-View-ViewModel,最初是微软在使用WindowsPresentationFoundation和SilverLight时定义的。2005年,JohnGrossman在一篇关于Avalon(WPF的代号)的博文中正式宣布了它的存在。如果你用过VisualStudio,新建一个WPF应用程序,然后在“设计”中拖入一个控件,双击后在“代码”中编写一个事件处理程序,或者绑定一个数据源。我对这个MVVM有点感觉。比如下面VS自动生成的代码:"/>
Hello<%=who%>
")的引用,//初始化方法initialize:function(){this.render();},//$el是一个缓存的jQuery对象render:function(){this.$el.html("HelloWorld");},//事件绑定events:{'keypress#new-todo':'createTodoOnEnter'}});varappview=newAppview();//model://每个应用的核心,包括交互数据和逻辑//比如数据校验、getter、setter、默认值、数据初始化、数据转换varapp={};app.Todo=Backbone.model.extend({defaults:{title:'',completed:false}});//创建模型实例vartodo=newapp.Todo({title:'LearnBackbone.js',completed:false});todo.get('title');//"LearnBackbone.js"todo.get('completed');//falsettodo.get('created_at');//undefinedtodo.set('created_at',Date());todo.get('created_at');//"我们dSep12201212:51:17GMT-0400(EDT)"//collection://一个有序的模型集合,可以设置或获取model//监听集合中的数据变化,从后端获取模型数据并持久化.app.TodoList=Backbone.Collection.extend({model:app.Todo,localStorage:newStore("backbone-todo")});//集合实例vartodoList=newapp.TodoList()todoList.create({title:'LearnBackbone\'sCollection'});//模型实例varmodel=newapp.Todo({title:'Learnmodels',completed:true});todoList.add(model);todoList.pluck('title');todoList.pluck('完全的');KnockoutJSnockoutJS是一个合法的MVVM框架,它通过简洁易读的数据绑定语法将DOM元素与viewmodel关联起来。当模型(viewmodel)的状态更新时,UI界面也会自动更新。viewmodel是模型和视图上的操作之间的连接,是一个纯Javascript对象。它不是UI,没有控件和样式的概念,也不是持久化的模型数据。它只是保存一些用户正在编辑的数据,然后公开操作(添加或删除)这些数据的方法。视图是视图模型中数据的可视化显示。视图观察视图模型。操作视图时,它向视图模型发送命令,并在视图模型发生变化时进行更新。视图和模型不知道彼此的存在。你的项目:
{{phone.snippet}}