原文链接:http://heroicyang.com/2012/08/08/to-backbone-tutorial-1/
最近一段时间来,才算是真正的开始深入学习JavaScript
,收获颇丰。也首次领略了前端MVC
架构的风采,现在前端MVC
的类库和框架越来越多,在经过初步的评估之后,决定先学习备受推崇的Backbone
。
以前自己做的一些Web
应用,基本上都是按照非常传统的方式:1.服务器端渲染模板;2.利用jQuery
的ajax
进行异步数据交换。所以首次接触前端架构类的东西,难免有点无从下手。经过几天的奋战,以及参阅国外大牛们的各种Tutorial
之后,终于拨开迷雾,缕了些头绪,自己也试着从传统的方式过渡(重构)出了所谓的架构性的代码。
整个重构的过程让我受益良多,所以决定再认真的记录一遍,加深自己的印象,也再确认一遍自己是否真的搞明白了,文章应该会比较长。
首先,先上一段所谓的传统式的代码。
$(function(){ $('#new-todo form').submit(function(e){ e.preventDefault(); var that = this; $.ajax({ url: '/add', type: 'POST', dataType: 'json', data: { todoContent: $(this).find('textarea').val() }, success: function(data){ $('#todo-list ul').append('<li>' + data.todoContent + '</li>'); $(that).find('textarea').val(''); } }); }); });
另外,也上一张关于这篇文章中涉及到的HTML
结构图,方便参照。由于文章稍长,我想如果直接在这里插图的话会影响阅读,所以就只给出图片链接了。
上面的一段代码我想应该都是大家非常熟悉的做法,因为我是一个伪前端攻城湿,所以我以前的代码中无不充斥着类似的、一堆一堆这样的代码。看上去貌似挺好的啊,也没啥问题,程序跑得倍儿棒。但是就这么短短的一段代码,它可干了不少事情:监听页面事件、用户事件、网络事件,接收用户的输入、执行网络的I/O、解析服务端返回的数据、动态生成HTML
结构,可谓是包罗万象啊,就这么短短的一段代码就解释了整个Web
应用程序的本质。
所以即便是这么一个小小的应用,逻辑和架构上都已经臃肿了,完全违反了咱们软件开发中的“单一职责原则”。如果是一个大应用,那估计就如乱麻———剪不断理还乱了。所以,改变迫在眉睫。
确实咱的要求也不高,如果把它搞成这样,其实咱就满足了:
- 在
$(document).ready
当中只保留一些应用程序的初始化代码即可,即应用的启动程序。 - 干掉乱如麻的逻辑,使得其符合咱们的“单一职责原则”,方便测试。
- 减小
ajax
和DOM
的耦合,其实也算是第2条。
OK,动手。按照最基本的重构方式,咱先把ajax
分离到一个方法里面去。
var addTodo = function(){ $.ajax({ url: '/add', type: 'POST', dataType: 'json', data: { todoContent: $('#new-todo').find('textarea').val() }, success: function(data){ $('#todo-list ul').append('<li>' + data.todoContent + '</li>'); $('#new-todo').find('textarea').val(''); } }); }; $(function(){ $('#new-todo form').submit(function(e){ e.preventDefault(); addTodo(); }); });
但是,在ajax
所在的方法中,data
和success
属性仍然保留了对DOM
的依赖,于是接下来将其调整为函数的参数来传递。
var addTodo = function(options){ $.ajax({ url: '/add', type: 'POST', dataType: 'json', data: { todoContent: options.todoContent }, success: options.success }); }; $(function(){ $('#new-todo form').submit(function(e){ e.preventDefault(); addTodo({ todoContent: $('#new-todo').find('textarea').val(), success: function(data){ $('#todo-list ul').append('<li>' + data.todoContent + '</li>'); $('#new-todo').find('textarea').val(''); } }); }); });
好像OK了,不过此时addTodo()
方法暴露在全局环境内,任何人都可以呼之欲来。我可不想当屌丝,作为一个富有上进心的、想成为一个合格前端攻城湿的我,还是给addTodo()
方法加个命名空间吧。
var TodoList = function(){}; TodoList.prototype.add = function(options){ $.ajax({ url: '/add', type: 'POST', dataType: 'json', data: { todoContent: options.todoContent }, success: options.success }); }; $(function(){ var todoList = new TodoList(); $('#new-todo form').submit(function(e){ e.preventDefault(); todoList.add({ todoContent: $('#new-todo').find('textarea').val(), success: function(data){ $('#todo-list ul').append('<li>' + data.todoContent + '</li>'); $('#new-todo').find('textarea').val(''); } }); }); });
现在submit
事件只依赖一个todoList
变量了,而且最重要的是现在的submit
事件中只关注DOM
操作了,干脆大刀阔斧的把它移到外层去。于是咱们引入视图View
了。
var TodoList = function(){}; TodoList.prototype.add = function(options){ $.ajax({ url: '/add', type: 'POST', dataType: 'json', data: { todoContent: options.todoContent }, success: options.success }); }; var NewTodoView = function(options){ var todoList = options.todoList; $('#new-todo form').submit(function(e){ e.preventDefault(); todoList.add({ todoContent: $('#new-todo').find('textarea').val(), success: function(data){ $('#todo-list ul').append('<li>' + data.todoContent + '</li>'); $('#new-todo').find('textarea').val(''); } }); }); }; $(function(){ var todoList = new TodoList(); new NewTodoView({ todoList: todoList }); });
恩,现如今$(document).ready
中就简洁得只剩我们之前所说的应用启动代码了。虽然代码已经组件化了,也工作得很好,但是仍然有需要重构的地方。NewTodoView
目前看上去都不怎么像一个对象的行为,所以继续重构之。
var TodoList = function(){}; TodoList.prototype.add = function(options){ $.ajax({ url: '/add', type: 'POST', dataType: 'json', data: { todoContent: options.todoContent }, success: options.success }); }; var NewTodoView = function(options){ this.todoList = options.todoList; $('#new-todo form').submit($.proxy(this.addTodo, this)); }; NewTodoView.prototype.addTodo = function(e){ e.preventDefault(); this.todoList.add({ todoContent: $('#new-todo').find('textarea').val(), success: function(data){ $('#todo-list ul').append('<li>' + data.todoContent + '</li>'); $('#new-todo').find('textarea').val(''); } }); }; $(function(){ var todoList = new TodoList(); new NewTodoView({ todoList: todoList }); });
这里用到了jQuery
中的$.proxy()
方法来解决this
作用域的问题,玩JavaScript
的童鞋们应该都很了解作用域这个东东。接下来,咱干点有关洁癖的事情,鉴于要保证代码的清晰、方便阅读,咱把success
里面的行为采用callback
的形式来完成。
/*前面不变*/ NewTodoView.prototype.addTodo = function(e){ e.preventDefault(); var that = this; this.todoList.add({ todoContent: $('#new-todo').find('textarea').val(), success: function(data){ that.appendTodo(data.todoContent); that.clearTextArea(); } }); }; NewTodoView.prototype.appendTodo = function(todoContent){ $('#todo-list ul').append('<li>' + todoContent + '</li>'); }; NewTodoView.prototype.clearTextArea = function(){ $('#new-todo').find('textarea').val(''); }; /*后面也不变*/
至此,重构的第一个版本其实就算得上大功告成了,已经达到前面提出的三大方针政策。文章果然比较长,所以我决定还是分成了上、下两节,当前这篇中完全没涉及到backbone
,所以到此就打住了,敬请关注下回分解。
另一篇更高层次上讲前端MVC的文章是:http://www.slideshare.net/enmaai/mvc-8825384
相关推荐
web前端框架MVC(backBone)实现记账应用,后端使用node.js(版本: lpNote-1.0),网上看到的,觉得不错上传上来,供大家一起共同分享学习。
Backbone.js和RequireJS TodoMVC示例 Backbone.js通过提供具有键值绑定和自定义事件的模型,具有丰富的可枚举函数的API,具有声明性事件处理的视图的集合,并通过RESTful JSON接口将其全部连接到您现有的API,从而为...
JS MVC框架(BackBone),主要包括两层:Model 和 View. Model 是用于数据交互 View 是用于界面显示的
##Backbone.js + Require.js Cart MVC-application with router 简单的购物车应用程序。
这个 Yeoman 生成器提供了一些使用基于 Browserify 和 Handlebars 的 Backbone 项目的快捷方式。 安装 $ npm install -g generator-backbone-browserify 搭建一个新项目 $ mkdir new_dir && cd new_dir $ yo ...
Backbone.js是十大JS框架之首,Backbone.js 是一个重量级js MVC 应用框架,也是js MVC框架的鼻祖。它通过Models数据模型进行键值绑定及custom事件处理,通过模型集合器Collections提供一套丰富的API用于枚举功能,...
晚上的技术演示将围绕 Backbone.js 库进行,重点介绍 JavaScript MV* 和 MVC 风格框架中涉及的设计模式。 我们将在演示期间构建一个简单的“在线植物园”应用程序。 我们恳请您是否愿意参加交互式开发会议,请携带...
主干MVC 基于主干。...例子/example/ 下有一些示例: requirejs展示了如何使用将 BackboneMVC 移植到您的项目中scaffold展示了使用 BackboneMVC 组织应用程序的常规方式。 有关完整的用户手册,请参阅 。
backbone教程 前端开发,前端MVC
BackboneJS示例代码用于学习目的。
骨干-wp 使用前端路由的 Backbone 构建的 WordPress 主题。 在阅读配套文章
npm install backbone-tableview --save 代码 CI TableView持续集成由Wercker处理: 测验 TableView保持100%的测试覆盖率。 要手动运行测试,请使用--dev进行安装(如上所述)并运行: gulp testc 您可以通过...
Backbone-tutorial:无脂肪的Backbone.js教程(绝对初学者的演练)
旧的自述文件:骨干素描这是一个集成以下内容的示例前端JavaScript项目: babel:将JavaScript 2015转换为JavaScript 5 主干:MV *框架引导程序:前端框架bower:前端程序包管理器柴:对于其“应” BDD断言库eslint...
Boilerplate-Backbone-Require 使用 RequireJS 和 Backbone 设置骨架项目结构的简单样板。 该项目设置了以下库: 需要文本和 css 插件骨干下划线jQuery 用户界面
前端开源库-backbone-callbacks主干回调,主干.js异步方法的匿名回调风格接口
技术选型:前端页面:Jquery + requireJS + underscore + backbone后端服务:Asp.net MVC + Mysql + EF6 + AOuth2身份验证项目结构:BnbjoyBackend.Site 后台管理站点BnbjoyBackend.Api Restful服务Bnbjoy.Business ...
骨干 Dropbox 数据存储适配器 v0.5.0 很简单,一个用于 Backbone 的 Dropbox Datastore 适配器。 它是 Backbone.Sync() 的直接替代品,用于处理保存到 。示例应用TodoMVC 有一个使用backbone.dropboxDatastore 作为...
1.backbone+require+jquery前端框架 2.包容性极强,现有的js插件几乎都能在本框架使用 3.健壮很稳定性极好。**开发了很多项目,都用的本框架,权限验证在本框架也很容易做 4.精心整理,有很多使用的注释,及文档支持
Backbone-demo 是一个简单的 JS 应用程序,用于向您展示 Backbone 模型、集合和视图的基础知识。 资源 Backbone.js: [ ] Underscore.js: [ ] jQuery:[ ] 小胡子:[ ] JSON 解析器:[ ] 用于文档的 JSDoc 工具...