浅谈使用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 相关文章推荐
js 加载并解析XML字符串的代码
Dec 13 Javascript
js中replace的用法总结
Dec 27 Javascript
javacript使用break内层跳出外层循环分析
Jan 12 Javascript
基于jQuery实现动态数字展示效果
Aug 12 Javascript
JS实现带关闭功能的阿里妈妈网站顶部滑出banner工具条代码
Sep 17 Javascript
jQuery ajax中使用confirm,确认是否删除的简单实例
Jun 17 Javascript
js中的关联数组与普通数组详解
Jul 27 Javascript
javascript循环链表之约瑟夫环的实现方法
Jan 16 Javascript
你真的了解BOM中的history对象吗
Feb 13 Javascript
javascript代码优化的8点总结
Jan 29 Javascript
开发Node CLI构建微信小程序脚手架的示例
Mar 27 Javascript
JavaScript 中的六种循环方法
Jan 06 Javascript
每天一篇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 Parse Error: syntax error, unexpected $end 错误的解决办法
2012/06/05 PHP
php读取图片内容并输出到浏览器的实现代码
2013/08/08 PHP
php实现在服务器上创建目录的方法
2015/03/16 PHP
详解yii2使用多个数据库的案例
2017/06/16 PHP
PHP数组常用函数实例小结
2018/08/20 PHP
php和C#的yield迭代器实现方法对比分析
2019/07/17 PHP
js+FSO遍历文件夹下文件并显示
2007/03/07 Javascript
javascript Zifa FormValid 0.1表单验证 代码打包下载
2007/06/08 Javascript
js点击出现悬浮窗效果不使用JQuery插件
2014/01/20 Javascript
现如今最流行的JavaScript代码规范
2014/03/08 Javascript
js 获取页面高度和宽度兼容 ie firefox chrome等
2014/05/14 Javascript
Jquery的each里用return true或false代替break或continue
2014/05/21 Javascript
setTimeout()递归调用不加引号出错的解决方法
2014/09/05 Javascript
javascript结合CSS实现苹果开关按钮特效
2015/04/07 Javascript
jquery拖拽排序简单实现方法(效果增强版)
2016/02/16 Javascript
javascript的几种写法总结
2016/09/30 Javascript
angular ng-repeat数组中的数组实例
2017/02/18 Javascript
JS去掉字符串前后空格或去掉所有空格的用法
2017/03/25 Javascript
vue router路由嵌套不显示问题的解决方法
2017/06/17 Javascript
浅谈ECMAScript6新特性之let、const
2017/08/02 Javascript
vue生成随机验证码的示例代码
2017/09/29 Javascript
python基础教程之分支、循环简单用法
2016/06/16 Python
对Python中9种生成新对象的方法总结
2018/05/23 Python
python3实现多线程聊天室
2018/12/12 Python
20行python代码的入门级小游戏的详解
2019/05/05 Python
Python实现自定义读写分离代码实例
2019/11/16 Python
python实现数据清洗(缺失值与异常值处理)
2019/12/02 Python
Python爬虫小例子——爬取51job发布的工作职位
2020/07/10 Python
main 函数执行以前,还会执行什么代码
2013/04/17 面试题
行政主管岗位职责
2013/11/18 职场文书
幼儿园新年寄语
2014/04/03 职场文书
北京奥运会主题口号
2014/06/13 职场文书
学校爱国卫生月活动总结
2014/06/25 职场文书
法学专业求职信
2014/07/15 职场文书
导游词之井冈山
2019/11/20 职场文书
详解Laravel制作API接口
2021/05/31 PHP