极乐门资源网 Design By www.ioogu.com

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

不太规范的代码的示例

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

$(function(){
  $('#form').submit(function(e) {
    e.preventDefault();
 
    $.ajax({
      url: '/animals',
      type: 'POST',
      dataType: 'json',
      data: { text: $('#new-animal').find('textarea').val() },
      success: function(data) {
        $('#animals').append('<li>' + data.text + '</li>');
        $('#new-animal').find('textarea').val('');
      }
     });
   });
});

维护这一类的代码将会很难。因为这短短的一段代码与很多地方都有关联: 它控制着很多的事件 (站点, 用户, 网络事件), 它要处理用户的操作事件, 要解析服务器返回的应答并且产生HTML代码。 有人可能说: “是的,你说的对, 但是如果这不是一个客户端单页的页面应用"htmlcode">

var Animals = function() {
};
 
Animals.prototype.add = function (options) {
   $.ajax({
     url: '/animals',
     type: 'POST',
     dataType: 'json',
     data: { text: options.text },
     success: options.success
   });
};
 
 var NewAnimalView = function (options) {
  this.animals = options.animals;
  var add = $.proxy(this.addAnimal, this);
  $('# form').submit(add);
 };
 
 NewAnimalView.prototype.addAnimal = function(e) {
   e.preventDefault();
   var self = this;
 
   this.animals.add({
     text: $('#new-animal textarea').val(),
     success: function(data) {
       self.appendAnimal (data.text);
       self.clearInput();     
     }
   });
 };
 
NewAnimalView.prototype.appendAnimal = function(text) {
  $('#animals ul').append('<li>' + data.text + '</li>');
};
NewAnimalView.prototype.clearInput = function() {
  $('#new-animal textarea').val('');
};
 
 $(document).ready(function() {
   var animals = new Animals();
   new NewAnimalView({ animals: animals });
 });

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

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

var events = _.clone(Backbone.Events);
var Animals = function() {
};
 
Animals.prototype.add = function(text) {
   $.ajax({
     url: '/animals',
     type: 'POST',
     dataType: 'json',
     data: { text: text },
     success: function(data) {
      events.trigger('animal:add', data.text);
     }
   });
};
 
var NewAnimalView = function(options) {
  this.animals = options.animals;
  events.on('animal:add', this.clearAnimal, this);
  var add = $.proxy(this.addAnimal, this);
  $('# form').submit(add);
 };
 
NewAnimalView.prototype.addAnimal = function(e) {
   e.preventDefault();
   this.animals.add($('#new-animal textarea').val());
 };
 
NewAnimalView.prototype.clearInput = function() {
  $('#new-animal textarea').val('');
};
 
var AnimalsView = function() {
  events.on('animal:add', this.appendAnimal, this);
};
 
AnimalsView.prototype.appendAnimal = function(text) {
  $('#animals ul').append('<li>' + data.text + '</li>');
};
 
$(document).ready(function() {
   var animals = new Animals();
   new NewAnimalView({ animals: animals });
   new AnimalsView();
});

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

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

var Animal = Backbone.Model.extend({
  url: '/animals'
});
 
var Animals = Backbone.Collection.extend({
  model: Animal
});
 
var AnimalsView = Backbone.View.extend({
  initialize: function() {
    this.collection.on('add', this.appendAnimal, this);
  },
 
  appendAnimal: function(animal) {
    this.$('ul').append('<li>' + animal.escape('text') + '</li>');
  }
});
 
 
var NewAnimalView = Backbone.View.extend({
  events: {
    'submit form': 'addAnimal'
  },
 
  initialize: function() {
    this.collection.on('add', this.clearInput, this);
  },
 
  addAnimal: function(e) {
    e.preventDefault();
    this.collection.create({ text: this.$('textarea').val() });
  },
 
  clearInput: function() {
    this.$('textarea').val('');
  }
});
 
$(document).ready(function() {
  var animals = new Animals();
  new NewAnimalView({ el: $('#new-animal'), collection: animals });
  new AnimalsView({ el: $('#animals'), collection: animals });
});

总结

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

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

标签:
JavaScript,客户端

极乐门资源网 Design By www.ioogu.com
极乐门资源网 免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
极乐门资源网 Design By www.ioogu.com

评论“对JavaScript客户端应用编程的一些建议”

暂无对JavaScript客户端应用编程的一些建议的评论...

《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线

暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。

艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。

《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。