浅谈使用MVC模式进行JavaScript程序开发


Posted in Javascript onNovember 10, 2015

随着前台开发日益受到重视,客户端代码比重日益增加的今天,如何在javascript开发里应用MVC模式,这个问题似乎会一直被提到,所以偶在这里粗略的谈一下自己的看法吧。

MVC模式的基本理念,是通过把一个application封装成model, view和controller三个部分达到降低耦合,简化开发的目的。这么说很空洞,大家可以实际看个例子:

<select id="selAnimal">
  <option value="cat">cat</option>
  <option value="fish">fish</option>
  <option value="bird">bird</option>
</select>
<p id="whatDoesThisAnimalDo"></p>

<script type="text/javascript">
document.getElementById('selAnimal').onchange = function() {
  var thisAnimalDoes;
  switch ( this.value ) {
    case 'cat':
      thisAnimalDoes = "cat meows";
      break;
    case 'fish':
      thisAnimalDoes = "fish swims";
      break;
    case 'bird':
      thisAnimalDoes = "bird flies";
      break;
    default:
      thisAnimalDoes = "wuff?";
  }
  document.getElementById('whatDoesThisAnimalDo').innerHTML = thisAnimalDoes;
}
</script>

这个小程序会把你从下拉菜单"selAnimal"中选择的动物能做什么事回显到网页上。以上是没有应用任何设计模式和编成思想写出的代码。如果要在这里应用MVC模式,代码又会变成怎样的呢?

<select id="selAnimal">
  <option value="cat">cat</option>
  <option value="fish">fish</option>
  <option value="bird">bird</option>
</select>
<p id="whatDoesThisAnimalDo"></p>

<script type="text/javascript">
// whatDoesAnimalDo 就是一个controller
var whatDoesAnimalDo = {
  // 选择视图
  start: function() {
    this.view.start();
  },
  // 将用户的操作映射到模型的更新上
  set: function(animalName) {
    this.model.setAnimal(animalName);
  },
};
// whatDoesAnimalDo的数据model
whatDoesAnimalDo.model = {
  // animal的数据
  animalDictionary: {
    cat: "meows",
    fish: "swims",
    bird: "flies"
  },
  // 当前的animal,也就是这个application的状态
  currentAnimal: null,
  // 数据模型负责业务逻辑和数据存储
  setAnimal: function(animalName) {
    this.currentAnimal = this.animalDictionary[animalName] ? animalName : null;
    this.onchange();
  },
  // 并且通知视图更新显示
  onchange: function() {
    whatDoesAnimalDo.view.update();
  },
  // 还需要响应视图对当前状态的查询
  getAnimalAction: function() {
    return this.currentAnimal ? this.currentAnimal + " " + this.animalDictionary[this.currentAnimal] : "wuff?";
  }
};
// whatDoesAnimalDo的视图
whatDoesAnimalDo.view = {
  // 用户输入触发onchange事件
  start: function() {
    document.getElementById('selAnimal').onchange = this.onchange;
  },
  // 该事件将用户请求发送给控制器
  onchange: function() {
    whatDoesAnimalDo.set(document.getElementById('selAnimal').value);
  },
  // 视图更新显示的方法,其中视图会向model查询当前的状态,并将其显示给用户
  update: function() {
    document.getElementById('whatDoesThisAnimalDo').innerHTML = whatDoesAnimalDo.model.getAnimalAction();
  }
};
whatDoesAnimalDo.start();
</script>

……突然一下代码变得好夸张e....
——偶都还没有在里面实现观察者模式呢...
实在太不良好了。

 

这样就带出了MVC模式最大的诟病:在简单的系统中应用MVC模式,会增加结构的复杂性,并且降低效率。

所以偶觉得除了少数javascript控件,比如click-anywhere-to-edit datagrid/tree control, 或者FckEditor/tinyMCE这样的支持自定义plugin的富文本编辑器非常适合应用MVC之外,在大多数的实用B/S系统中,javascript开发只要遵循工厂模式就足够让你受益匪浅了。这是由于前端开发和后段开发的性质不同引起的。如果在ASP.net或者JSP项目中应用MVC模式,SDK或多或少会自动生成一些view和controller的代码。但是javascript呢——javascript甚至连个好用的SDK都没有,虽然有不少成熟的framework,但最终还是会大大增加开发量。

与开发量相比,更加令人头疼的是效率的问题。三层之间的相互通信都是额外的开销。对于服务器端,这些通信造成的开销几乎可以忽略不计。但对于javascript这样相对低效率的语言,多几重调用和事件侦听就能明显感觉到性能的下降了。而且,因为javascrip的闭包特性,一不小心就搞出内存泄漏,这可是正宗的偷鸡不成蚀把米了...
所以,对于javascript开发,适度开发可能比应用你所学到的学术知识更重要,毕竟前端开发是以解决实际问题为基础,而不是为了炫技。当然,Dflying gg有句话叫“重构无处不在”——如果你觉得你自己的代码越来越乱,维护起来越来越困难,那么,你就该考虑是不是该用MVC重构一下了~

 

再额外的说一句:是不是整个前端开发就不必使用MVC了呢?no no~ 其实整个前端开发就是一个大大的MVC架构啊——

Model: HTML/XHTML中的信息
View: Style sheet
Controller: EMAScripts等等脚本
这不正是web标准的最终目的么....

所以,把握好整个前端代码的结构,永远比在javascript开发中过量应用设计模重要的多!

不过,也有一些优秀的MVC框架,对此西雅图的一位黑客和设计师Gordon L. Hempton做了一下对比,这里我们拉过来看一下:

1. Backbone.js——优点:强大的社区,强劲的势头;缺点:抽象较弱,很多功能亟待增加。
2. SproutCore——优点:对绑定的支持,可靠的社区,大量特性;缺点:过度规范,难以和不需要的特性解耦。
3. Sammy.js——优点:易于学习,更容易和现存的服务端应用程序整合;缺点:过于简单,无法应用于大型应用程序中。
4. Spine.js——优点:轻量级,文档很完备;缺点:它的核心概念“spine”是异步的用户界面,这意味着理想状况用户界面永远不会发生堵塞,而这个基础有缺陷。
5. Cappuccino——优点:大型深思熟虑后的框架,良好的社区,很棒的继承模型;缺点:由iOS开发者创建,使用JavaScript模拟Objective-C。
6. Knockout.js——优点:对绑定的支持,完备的文档和教程;缺点:绑定语法拙劣,缺少统一的视图组件层级关系。
7. Javascript MVC——优点:可靠的社区;缺点:基于字符串的继承模型很差,控制器与视图关系过密而缺少绑定。
8. GWT(Google Web Toolkit)——优点:全面的框架,良好的社区,可靠的基于Java的组件继承模型;缺点:可能无法经受时间的考验,另外,Java在客户端上的抽象有些笨拙。
9. Google Closure——优点:很好的基于组件的UI组合系统。缺点:缺少UI绑定支持。
10. Ember.js——优点:很丰富的模板系统,拥有复合视图和UI绑定;缺点:相对较新,文档不够完备。
11. Angular.js——优点:对模板范围和控制器设计有很好的考虑,拥有依赖注入系统,支持丰富的UI绑定语法。缺点:代码的模块性不强,视图的模块化也不够。
12. Batman.js——优点:代码清晰,绑定、持久化的方法简单;缺点:使用了单例控制器。

Javascript 相关文章推荐
jQuery学习笔记之jQuery的事件
Dec 22 Javascript
关于页面嵌入swf覆盖div层的问题的解决方法
Feb 11 Javascript
angularjs客户端实现压缩图片文件并上传实例
Jul 06 Javascript
改变checkbox默认选中状态及取值的实现代码
May 26 Javascript
微信小程序 开发之快递查询功能的实现
Jan 09 Javascript
微信小程序 video详解及简单实例
Jan 16 Javascript
js控制文本框禁止输入特殊字符详解
Apr 07 Javascript
node中使用es5/6以及支持性与性能对比
Aug 11 Javascript
详解html-webpack-plugin插件(用法总结)
Sep 12 Javascript
es6函数之rest参数用法实例分析
Apr 18 Javascript
如何在微信小程序中使用骨架屏的步骤
Jun 12 Javascript
vue中封装axios并实现api接口的统一管理
Dec 25 Vue.js
每天一篇javascript学习小结(基础知识)
Nov 10 #Javascript
jQuery+CSS3实现3D立方体旋转效果
Nov 10 #Javascript
JavaScript中利用各种循环进行遍历的方式总结
Nov 10 #Javascript
简单学习JavaScript中的for语句循环结构
Nov 10 #Javascript
js密码强度校验
Nov 10 #Javascript
详解javascript函数的参数
Nov 10 #Javascript
JavaScript函数的一些注意要点小结及js匿名函数
Nov 10 #Javascript
You might like
php将session放入memcached的设置方法
2014/02/14 PHP
PHP简单获取网站百度搜索和搜狗搜索收录量的方法
2016/08/23 PHP
ThinkPHP框架结合Ajax实现用户名校验功能示例
2019/07/03 PHP
Jquery 学习笔记(一)
2009/10/13 Javascript
javascript利用初始化数据装配模版的实现代码
2010/11/17 Javascript
jquery $.ajax()取xml数据的小问题解决方法
2010/11/20 Javascript
JQuery控制div外点击隐藏而div内点击不会隐藏的方法
2015/01/13 Javascript
AngularJS模块管理问题的非常规处理方法
2015/04/29 Javascript
jquery实现清新实用的网页菜单效果
2015/08/28 Javascript
js仿支付宝填写支付密码效果实现多方框输入密码
2016/03/09 Javascript
ionic 上拉菜单(ActionSheet)实例代码
2016/06/06 Javascript
JavaScript数据结构之二叉查找树的定义与表示方法
2017/04/12 Javascript
利用jquery如何从json中读取数据追加到html中
2017/12/01 jQuery
深入浅析AngularJs模版与v-bind
2018/07/06 Javascript
如何安装控制器JavaScript生成插件详解
2018/10/21 Javascript
[46:20]CHAOS vs Alliacne 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
python二分法实现实例
2013/11/21 Python
Python lxml模块安装教程
2015/06/02 Python
tensorflow 加载部分变量的实例讲解
2018/07/27 Python
python爬虫之urllib库常用方法用法总结大全
2018/11/14 Python
浅谈Python爬虫原理与数据抓取
2020/07/21 Python
python 实现图片修复(可用于去水印)
2020/11/19 Python
使用HTML5原生对话框元素并轻松创建模态框组件
2019/03/06 HTML / CSS
DHC中国官方购物网站:日本通信销售No.1化妆品
2016/08/20 全球购物
印度在线购物网站:Paytmmall
2019/07/24 全球购物
莱德杯高尔夫欧洲官方商店:Ryder Cup Shop
2019/08/14 全球购物
C#里面如何判断一个Object是否是某种类型(如Boolean)?
2016/02/10 面试题
《青山处处埋忠骨》教学反思
2014/04/22 职场文书
2014优秀党员事迹材料
2014/08/14 职场文书
2014年基层党建工作总结
2014/11/11 职场文书
村官2015年度工作总结
2015/10/14 职场文书
2016年教师节特级教师获奖感言
2015/12/09 职场文书
2019年描写人生经典诗句大全
2019/07/08 职场文书
php 原生分页
2021/04/01 PHP
Redis 持久化 RDB 与 AOF的执行过程
2021/11/07 Redis
宝塔更新Python及Flask项目的部署
2022/04/11 Python