构建更好的客户端 JavaScript 应用

你可能注意到了,最近的一段时间越来越多的Web应用有变复杂的趋势,重心从服务端慢慢向着客户端转移。 这是个正常的趋势么?我不知道。支持和反对者的讨论就像是在讨论复活者和圣诞节哪一个更好一样; 很难说哪一方观点就是完全正确的。因此,本文不会探讨究竟哪一方是对的,不过我还是试图解释一下使用大家所熟知的面向对象编程也许可以成功的解决客户端编程中存在的一些问题。

不太规范的代码的示例

为了顾及一个应用的响应以及用户体验, 导致我们创建了持续增长的复杂的代码, 这些代码变得难于理解和维护。 你可以轻松的想到在没有任何构架和遵循规则构建出客户端的JavaScript应用代码将会这样:

01 $(function(){
02     $(‘#form‘).submit(function(e) {
03         e.preventDefault();
04  
05         $.ajax({
06             url: ‘/animals‘,
07             type: ‘POST‘,
08             dataType: ‘json‘,
09             data: { text: $(‘#new-animal‘).find(‘textarea‘).val() },
10             success: function(data) {
11                 $(‘#animals‘).append(‘<li>‘ + data.text + ‘</li>‘);
12                 $(‘#new-animal‘).find(‘textarea‘).val(‘‘);
13             }
14          });
15      });
16 });

维护这一类的代码将会很难。因为这短短的一段代码与很多地方都有关联: 它控制着很多的事件 (站点, 用户, 网络事件), 它要处理用户的操作事件, 要解析服务器返回的应答并且产生HTML代码。 有人可能说: “是的,你说的对, 但是如果这不是一个客户端单页的页面应用?这最多算是一次过度使用jQuery类库的例子” ——不是很有说服力的观点, 因为众所周知,易于维护和精心设计的代码是非常重要的。特别是许多的工具或者是框架致力于保持代码可用以便于我们能更简单的去测试、维护、重用、和扩展它。

MV*是什么?

谈到这里。我们能受益于那些基于MVC的JavaScript框架,但这些框架大部分不使用MVC,并且相当于Model和Videw的一种结合,或者在二都之间的一些东西,这很难去分清。这就是为什么说大部分的Javascript框架是基于MV*。

改变方法或许可以提供项目中客户端的组织和架构,这使得代码可以在很长的一段时间内容易维护,即使重构已经有的代码也变得相对容易。知道他如何工作和下面一些问题的答案是必需要要记住的。

  • 我的应用里有哪些类型的数据?-Model
  • 用户应该看到什么?-View
  • 谁是和用户交互的程序?-Controller

使用MVC框架重构代码

受用MVC重构代码有什么好处?

  • 解除DOM和Ajax的依赖
  • 代码有更好的结构,并且更容易测试。
  • 从 $(document).ready()中删除多余的代码,只留下使用Model创建Links的部分。

让我们使用一些简单步骤来重构一个典型的代码块

步骤 1: 创建视图并移动Ajax请求

我们开始解除DOM和Ajax的依赖. 使用prototypes建造者,模式创建‘Animals‘ 对象,并且添加一个 ‘add‘ 方法.同时创建视图‘NewAnimalView‘ , 并且添加方法‘addAnimal‘、 ‘appendAnimal‘ 、‘clearInput‘.

代码如下:

01 var Animals = function() {
02 };
03  
04 Animals.prototype.add = function (options) {
05      $.ajax({
06          url: ‘/animals‘,
07          type: ‘POST‘,
08          dataType: ‘json‘,
09          data: { text: options.text },
10          success: options.success
11      });
12 };
13  
14  var NewAnimalView = function (options) {
15     this.animals = options.animals;
16     var add = $.proxy(this.addAnimal, this);
17     $(‘# form‘).submit(add);
18  };
19  
20  NewAnimalView.prototype.addAnimal = function(e) {
21      e.preventDefault();
22      var self = this;
23  
24      this.animals.add({
25          text: $(‘#new-animal textarea‘).val(),
26          success: function(data) {
27              self.appendAnimal (data.text);
28              self.clearInput();          
29          }
30      });
31  };
32  
33 NewAnimalView.prototype.appendAnimal = function(text) {
34     $(‘#animals ul‘).append(‘<li>‘ + data.text + ‘</li>‘);
35 };
36 NewAnimalView.prototype.clearInput = function() {
37     $(‘#new-animal textarea‘).val(‘‘);
38 };
39  
40  $(document).ready(function() {
41      var animals = new Animals();
42      new NewAnimalView({ animals: animals });
43  });

步骤 2: 使用事件解除依赖.

这个例子,利用MVC框架是关键。我们将会用到事件机制, 事件使我们结合和触发自定义事件. 因此,我们创建新的“AnimalsView”和“NewAnimalView”,并且赋予它们不同的显示animals的职责。 使用事件就来区别职责非常简单。如果在方法和事件之间传递职责,如下所示:

01 var events = _.clone(Backbone.Events);
02 var Animals = function() {
03 };
04  
05 Animals.prototype.add = function(text) {
06      $.ajax({
07          url: ‘/animals‘,
08          type: ‘POST‘,
09          dataType: ‘json‘,
10          data: { text: text },
11          success: function(data) {
12             events.trigger(‘animal:add‘, data.text);
13          }
14      });
15 };
16  
17 var NewAnimalView = function(options) {
18     this.animals = options.animals;
19     events.on(‘animal:add‘this.clearAnimal, this);
20     var add = $.proxy(this.addAnimal, this);
21     $(‘# form‘).submit(add);
22  };
23  
24 NewAnimalView.prototype.addAnimal = function(e) {
25      e.preventDefault();
26      this.animals.add($(‘#new-animal textarea‘).val());
27  };
28  
29 NewAnimalView.prototype.clearInput = function() {
30     $(‘#new-animal textarea‘).val(‘‘);
31 };
32  
33 var AnimalsView = function() {
34     events.on(‘animal:add‘this.appendAnimal, this);
35 };
36  
37 AnimalsView.prototype.appendAnimal = function(text) {
38     $(‘#animals ul‘).append(‘<li>‘ + data.text + ‘</li>‘);
39 };
40  
41 $(document).ready(function() {
42      var animals = new Animals();
43      new NewAnimalView({ animals: animals });
44      new AnimalsView();
45 });

步骤 3: 传递数据结构到核心框架

最后,最重要的一步,我们使用: models, views and collections.

view source

print?

01 var Animal = Backbone.Model.extend({
02     url: ‘/animals‘
03 });
04  
05 var Animals = Backbone.Collection.extend({
06     model: Animal
07 });
08  
09 var AnimalsView = Backbone.View.extend({
10     initialize: function() {
11         this.collection.on(‘add‘this.appendAnimal, this);
12     },
13  
14     appendAnimal: function(animal) {
15         this.$(‘ul‘).append(‘<li>‘ + animal.escape(‘text‘) + ‘</li>‘);
16     }
17 });
18  
19  
20 var NewAnimalView = Backbone.View.extend({
21     events: {
22         ‘submit form‘‘addAnimal‘
23     },
24  
25     initialize: function() {
26         this.collection.on(‘add‘this.clearInput, this);
27     },
28  
29     addAnimal: function(e) {
30         e.preventDefault();
31         this.collection.create({ text: this.$(‘textarea‘).val() });
32     },
33  
34     clearInput: function() {
35         this.$(‘textarea‘).val(‘‘);
36     }
37 });
38  
39 $(document).ready(function() {
40     var animals = new Animals();
41     new NewAnimalView({ el: $(‘#new-animal‘), collection: animals });
42     new AnimalsView({ el: $(‘#animals‘), collection: animals });
43 });

总结

我们已经实现什么呢?我们在高度的抽象上工作。代码的维护、重构和扩展变得更容易。我们极大的优化了代码结果,是不是很迷人?太棒了。但是,我可能要给你泼冷水,即使最好的框架,开发的代码仍旧是脆弱并且难以维护。因此,如果你认为使用了一个较好的MV*框架能解决所有代码上的问题是错误的。记住在重构过程中,经历了第二步,代码会变得好很多,我们不使用框架的主要组件。

记住MV*框架是好的这一点,但是所有关注在‘How’去开发一个应用,这让程序开发人员头决定‘What’。每个框架的一个补充,尤其是当项目的Domain很复杂,将是Domain驱动设计方法,这将更关注与下面的方面:“what”, 把需求转化为真正的产品的一个过程。但是,这是我们要讨论的另外一个主题。

构建更好的客户端 JavaScript 应用

时间: 2024-08-28 09:34:41

构建更好的客户端 JavaScript 应用的相关文章

使用 jQuery UI 和 jQuery 插件构建更好的 Web 应用程序

简介: 对于那些使用 JavaScript 和 jQuery 库从桌面应用程序转向 Web 应用程序的开发人员来说,他们还不习惯去考虑应用程序基本的外观,因为这些以前都是由操作系统来处理的.了解 jQuery UI,一个基于 jQuery 的 UI 工具箱,使创建漂亮的界面更为容易.本文同时也介绍了一些 jQuery 插件,可以加速 Web 开发并有助于创建我们所熟悉的,且流畅.直观.灵活的界面. 简介 如果您是一个传统桌面应用程序开发人员,并且正在转向开发 Web 应用程序,在学习 HTML

JavaScript 客户端JavaScript之事件(DOM API 提供模块之一)

具有交互性的JavaScript程序使用的是事件驱动的程序设计模型. 目前使用的有3种完全不同的不兼容的事件处理模型. 1.原始事件模型 (一种简单的事件处理模式) 一般把它看作0级DOM API的一部分内容,所有启用了JavaScript的浏览器都支持它,因此它具有可移植性. 2.标准事件模型 (一种强大的具有完整性的事件模型) 2级DOM标准对它进行了标准化,除IE以外的所有浏览器都支持它. 3.IE事件模型 想用高级事件处理特性的JavaScript程序设计者必须为IE浏览器编写特定的代码

T3 - 构建大型 Web 应用的 JavaScript 框架

T3 是一个用于构建大型 Web 应用程序的客户端 JavaScript 框架.T3 和大多数的 JavaScript 框架不同.它的意思是一小部分的整体架构,它允许你建立可扩展的客户端代码.T3 应用程序是由应用程序对象管理,主要任务是管理模块,服务和行为.这是这三种类型的对象,允许你建立一个可扩展的 JavaScript 前端的组合. 在线演示      源码下载 您可能感兴趣的相关文章 网站开发中很有用的 jQuery 效果[附源码] 分享35个让人惊讶的 CSS3 动画效果演示 十分惊艳

前端--关于客户端javascript

客户端javascript就是运行在浏览器中的javascript,现代的浏览器已经有了很好的发展,虽然它是一个应用程序,但完全可以把它看作是一个简易的操作系统.因为像windows.linux等操作系统为人们提供的文档存储.网络调用.绘制各种可视化图像等功能在浏览器中也同样都可以得到支持,所以就像操作系统中的程序叫做桌面应用一样,浏览器中内容丰富.可互动的web文档也叫做web应用. web应用不像桌面应用,通常情况下桌面应用所需要的资源绝大部分都已经在本地部署好了,所以桌面应用的反应速度是非

JavaScript 客户端JavaScript之脚本化HTTP(通过XMLHttpRequest)

XMLHttpRequest对象的设计目的是为了处理由普通文本或XML组成的响应:但是,一个响应也可能是另外一种类型,如果用户代理(UA)支持这种内容类型的话. 大多数浏览的客户端JavaScript都包含此功能. HTTP协议 规定了Web浏览器如何从Web服务请求文档,如何向Web服务器传送表单内容,以及如何响应 这些请求和传递. Web浏览器处理了很多HTTP(通常HTTP并不在脚本的控制之下) 1.用户点击一个链接 2.提交一个表单 3.输入一个URL 通常JavaScript代码可能脚

RequestAnimationFrame更好的实现Javascript动画

一直以来,JavaScript的动画都是通过定时器和间隔来实现的.虽然使用CSS transitions 和 animations使Web开发实现动画更加方便,但多年来以JavaScript为基础来实现动画却很少有所改变.直到Firefox 4的发布,才带来了第一种对JavaScript动画的改善的方法.但要充分认识改善,这有利于帮助我们了解web动画是如何演变改进的. 定时器Timer 用于创建动画的第一个模式是使用链式setTimeout()调用.在Netscape 3′s hayday的很

[iOS]将DataSource分离并构建更轻量的UIViewController

在objccn.io中看到一篇文章,构建更轻量的View Controllers,在此自己实践一下加深理解. 新疆项目,learn--tableview,类前缀为LT,开始我们的实验. 首先需要在StoryBoard中拖拽一个UITableView,在头文件中申明tableView变量并建立连接: 新建ArrayDataSource类,作为TableView的DataSource.目的是将DataSource从原本的ViewController中分离出来: // // ArrayDataSour

Android—构建安全的Android客户端请求,避免非法请求

今天通过实例来介绍一下如何构建安全的Android客户端请求,避免非法请求: [0分下载Demo]

JavaScript 客户端JavaScript之cookie和客户端持久性

Document对象都有一个cookie属性,它使得JavaScript代码能够在用户的硬盘上持久地存储数据, 并且能够获取以这种方式存储的数据.客户端持久性是赋予WEB应用程序记忆力的一种简单方法. cookie还可以用于客户端脚本化,并且是HTTP协议的一个标准扩展. cookie的字符串由  名字/值 组成 (=区分),不同的属性之间用分号隔开. cookie有4个可选属性 1.expires(已被max-age取代)  生存期 expires是未来的一个过期日期,max-age用秒来设置