你可能注意到了,最近的一段时间越来越多的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代码。 有人可能说: “是的,你说的对, 但是如果这不是一个客户端单页的页面应用?这最多算是一次过度使用jQuery类库的例子” ——不是很有说服力的观点, 因为众所周知,易于维护和精心设计的代码是非常重要的。特别是许多的工具或者是框架致力于保持代码可用以便于我们能更简单的去测试、维护、重用、和扩展它。
MVC是什么?
谈到这里。我们能受益于那些基于MVC的JavaScript框架,但这些框架大部分不使用MVC,并且相当于Model和Videw的一种结合,或者在二都之间的一些东西,这很难去分清。这就是为什么说大部分的Javascript框架是基于MV*。
改变方法或许可以提供项目中客户端的组织和架构,这使得代码可以在很长的一段时间内容易维护,即使重构已经有的代码也变得相对容易。知道他如何工作和下面一些问题的答案是必需要要记住的。
使用MVC框架重构代码
受用MVC重构代码有什么好处?
让我们使用一些简单步骤来重构一个典型的代码块
步骤 1: 创建视图并移动Ajax请求
我们开始解除DOM和Ajax的依赖. 使用prototypes建造者,模式创建'Animals' 对象,并且添加一个 'add' 方法.同时创建视图 'NewAnimalView' , 并且添加方法'addAnimal'、 'appendAnimal' 、'clearInput'.
代码如下:
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”, 把需求转化为真正的产品的一个过程。但是,这是我们要讨论的另外一个主题。
我需要一个用于java spring应用程序的graphQL客户端,以与另一个基于graphQL API的微服务通信。我知道Apollo Android,但它似乎没有用maven实现(也许你知道maven的一些链接或示例等)。有什么想法和建议吗?提前感谢!
问题内容: 我有以下代码: 为什么这不将“ bar”写入我的文本文件,而是发出“ 42”警报? 注意:此问题的早期修订版本明确涉及服务器上的PHP和客户端上的JavaScript。当一种语言在客户端上运行而另一种语言在服务器上运行时,问题和解决方案的本质对于 任何 一对语言都是相同的(即使它们是相同的语言)。当您看到有关特定语言的答案时,请考虑到这一点。 问题答案: 您的代码分为两个完全独立的部分
创建客户端有两种方式,一种是直接使用特化的构造器函数,另一种是使用工厂构造器函数。 第一种方式返回的是具体的客户端结构体指针对象,第二种方式返回的是客户端接口对象。 使用特化的构造器函数创建客户端 特化的构造器函数有下面几个: func NewHTTPClient(uri ...string) (client *HTTPClient) func NewTCPClient(uri ...string
问题内容: 我正在玩RESTEasy以使用REST服务,并且正在使用Twitter的搜索API进行尝试。 所以我创建了这个接口: 并用以下命令调用它: 但是我得到了: ClientResponseFailure:无法找到内容类型为application / json; charset =“ utf-8”的MessageBodyReader并键入接口java.util.Set 我尝试使用POJO而不
我试图从一个简单的独立Java客户端(一个类)以编程方式在WebLogic(10.3.4)中创建用户-- } 关于我应该做什么样的上下文查找,有什么想法吗?“java:comp”抛出一个javax。命名。NameNotFoundException;看起来我只能在容器中使用它。
轻推支持在电脑端和手机端创建轻应用,创建完成后待管理员审核通过后即创建成功,但仍需登录电脑端轻推进入企业管理设置轻应用。 1. 手机端 轻应用-添加-新建-设置轻应用头像-输入轻应用名称-选择所属企业-提交申请 2.电脑端 电脑端操作与手机端相同。
我想创建一个服务,可以拒绝\撤销对用户的移动邮件应用程序的访问。 具体来说,我想暂时撤销使用office365在线交换邮件对移动邮件客户端应用程序(如Nine)的访问,该应用程序被认证为Azure Active Directory应用程序。 到目前为止,我想出了如何执行类似或部分操作: > 我可以使用此链接手动撤消azure AD应用:https://account.activedirectory
让我们假设以下两种情况,一个控制器产生一些随机数并带有延迟: 1)反应性Spring5反应性应用: 2)传统的Spring MVC与: 从HTTP客户端(浏览器、AJAX请求)的角度来看,这两种场景之间没有任何区别。我的意思是,客户端将等待所有结果发送,并且在提交整个响应之前不会处理它们。 也就是说,尽管spring web Responsive让我们认为它在生成结果时会将结果发送回去,但实际上情