Javascript Web应用开发之:MVC模式

日期: 2012-06-26 来源:TechTarget中国 英文

  MVC是一种设计模式,它将应用划分为3个部分:数据(模型)、展现层(视图)和用户交互层(控制器)。换句话说,一个事件的发生是这样的过程:

  1. 用户和应用产生交互。

  2. 控制器的事件处理器被触发。

  3. 控制器从模型中请求数据,并将其交给视图。

  4. 视图将数据呈现给用户。

  现在来看一个真实的例子,图1-1 展示了在Holla 中如何发送新的聊天消息。

javascript mvc web应用

图1-1:从Holla中发送一个新的聊天消息

  1. 用户提交一个新的聊天消息。

  2. 控制器的事件处理器被触发。

  3. 控制器创建了一个新的聊天模型(Chat Model)记录。

  4. 然后控制器更新视图。

  5. 用户在聊天窗口看到新的聊天消息。

  我们不用类库或框架就可以实现这种MVC架构模式。关键是要将MVC的每部分按照职责进行划分,将代码清晰地分割为若干部分,并保持良好的解耦。这样可以对每个部分进行独立开发、测试和维护。

  下面来详细讲解MVC中的各个组成部分。

  模型

  模型用来存放应用的所有数据对象。比如,可能有一个User模型,用以存放用户列表、它们的属性及所有与模型有关的逻辑。

  模型不必知晓视图和控制器的细节,模型只需包含数据及直接和这些数据相关的逻辑。任何事件处理代码、视图模板,以及那些和模型无关的逻辑都应当隔离在模型之外。将模型和视图的代码混在一起,是违反MVC架构原则的。模型是最应该从你的应用中解耦出来的部分。

  当控制器从服务器抓取数据或创建新的记录时,它就将数据包装成模型实例。也就是说,我们的数据是面向对象的(object oriented),任何定义在这个数据模型上的函数或逻辑都可以直接被调用。

  因此,不要这样做:

  var user = users[“foo”];
  destroyUser(user);

  而要这样做:

  var user = User.find(“foo”);
  user.destroy();

  第1段代码没有命名空间的概念,并且不是面向对象的。如果在应用中定义了另一个destroyUser() 函数的话,两个函数就会产生冲突。我们应当确保全局变量和函数的个数尽可能少。在第2段代码中,destroy() 函数是存放在命名空间User 的实例中的,User中存放了所有的记录。当然这只是理想状况,因为我们控制了全局变量的个数,更好地避免了潜在的冲突,这种代码更加清晰,而且非常容易做继承,类似destroy() 的这种函数就不用在每个模型中都定义一遍了。

  视图

  视图层是呈现给用户的,用户与之产生交互。在JavaScript应用中,视图大都是由HTML、CSS 和JavaScript模板组成的。除了模板中简单的条件语句之外,视图不应当包含任何其他逻辑。

  实际上,和模型类似,视图也应当从应用的其他部分中解耦出来。视图不必知晓模型和控制器中的细节,它们是相互独立的。将逻辑混入视图之中是编程的大忌。

  这并不是说MVC不允许包含视觉呈现相关的逻辑,只要这部分逻辑没有定义在视图之内即可。我们将视觉呈现逻辑归类为“视图助手”(helper):和视图有关的独立的小型工具函数。

  来看下面的例子,其在视图中包含了逻辑,这是一个反例,平时不应当这样做:

  // template.html
  ${ formatDate(this.date) }

  在这段代码中,我们把formatDate() 函数直接插入视图中,这违反了MVC的原则,结果导致标签看上去像大杂烩一样不可维护。可以将视觉呈现逻辑剥离出来放入视图助手中,正如下面的代码就避免了这个问题,可以让这个应用的结构满足MVC。

  // helper.js
  var helper = {};
  helper.formatDate = function(){ /* … */ };
  // template.html
  ${ helper.formatDate(this.date) }

  此外,所有视觉呈现逻辑都包含在helper变量中,这是一个命名空间,可以防止冲突并保持代码清晰、可扩展。

  不要太在意视图和模板的细节,本小节的目的只是简单介绍视图和MVC架构模式之间的联系。

  控制器

  控制器是模型和视图之间的纽带。控制器从视图获得事件和输入,对它们(很可能包含模型)进行处理,并相应地更新视图。当页面加载时,控制器会给视图添加事件监听,比如监听表单提交或按钮点击。然后,当用户和你的应用产生交互时,控制器中的事件触发器就开始工作了。

  不用使用类库和框架也能实现控制器,下面这个例子就是使用简单的jQuery 代码来实现的:

  var Controller = {};
  // 使用匿名函数来封装一个作用域
  (Controller.users = function($){
  var nameClick = function(){
  /* … */
  };
  // 在页面加载时绑定事件监听
  $(function(){
  $(“#view .name”).click(nameClick);
  });
  })(jQuery);

  我们创建了users控制器,这个控制器是放在Controller变量下的命名空间。然后,我们使用了一个匿名函数封装了一个作用域,以避免对全局作用域造成污染。当页面加载时,程序给视图元素绑定了click事件的监听。

  正如你所看到的,控制器并不依赖类库或框架。然而,为了构建需要的一个完整的MVC框架,我们需要将模型从视图中抽离出来。

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐

  • AWS MEAN堆栈+JavaScript=快速搭建应用

    开发人员在构建Web应用时有许多选择。市面上有无数的框架和语言可选,而像AWS这样的云平台可以方便地部署和扩展应用程序。

  • JDK 8u40更新:新增功能抢先看

    俗话说长江后浪推前浪,一代新人换旧人,Java更新版本交替,也是这样一个道理。甲骨文又给Java添加了哪些新功能。

  • 移动浏览器到云:JavaScript地位正在扩张

    不难发现人们非常喜欢在前端开发中使用JavaScript。但是,令我们惊讶的是后端开发也如此青睐JavaScript,促进了基于云和基于数据中心的托管应用的发展。

  • 移动HTML5挑战何在?

    当HTML5出现时,许多开发者和应用架构师视之为创建平台独立应用、简化你的设备支持以及当新的移动设备OS版本发布时减少应用相关问题的机会。