什么是 Backbone.js
Backbone.js 是一个在JavaScript环境下的 模型-视图-控制器 (MVC) 框架。任何接触较大规模项目的开发人员一定会苦恼于各种琐碎的事件回调逻辑、以及金字塔般的代码。而且,在传统的Web应用程序代码中,不可避免的都有在应用逻辑中加入显示数据的代码的情况。当项目规模愈发变大时,这种形式的代码变得越发的难以维护,因为任何在主干逻辑中的变更都可能影响到数据显示逻辑,反之亦然。
Backbone就是要来解决这样的代码耦合的问题。它通过提供一个控制层-显示层的框架,以及模版(template)来分离各自逻辑。这样的MVC框架类似于传统意义上桌面程序以及服务器端程序的程序框架。
模型 Model
运用Backbone框架的程序的核心是“模型”。多数情况下,“模型”代表了数据库中存储的一种对象结构。
Backbone的设计思想是,让模型服务于存储、获取和更改数据。注意,有另外一些MVC框架的设计是让控制器负责更改数据。可是backbone的设计思想是,控制器的作用仅仅是用来处理从视图层来的用户请求、以及访问相对应的模型层。而模型层自身则需要负责(从数据源中)获取数据、以及数据封装。
下面的例子阐释了在Backbone里,数据模型是怎样声明和初始化的。
Stooge = Backbone.Model.extend({
defaults: {
'name': 'Guy Incognito',
'power': 'Classified',
'friends': [],
},
initialize: function () {
// Do initialization
}
});
var account = new Stooge({
name: 'Larry',
power: 'Baldness',
friends: ['Curly', 'Moe']
});
在backbone中,要创建“模型”,可以扩展 Backbone.Model 并且提供实例的属性。在上述例子中, extend 函数给 Stooge 类建立了一个原型链,因此只需要通过Stooge你就可以访问 模型 中的所有属性。并且,由于 extend 正确的设置了原型链,因此通过 extend 创建的子类 (subclasses) 也可以被深度扩展。Extend在backbone中是很重要的概念,在多数JavaScript库里面,extend函数用来处理从一个对象复制到另一个对象。在backbone里面,extend函数同样也会创建一个构造函数,因此你可以用来初始化一个类,再把它复制到新的类,从而达到多层扩展。
视图 View
视图表示了在一种“模型”的基础上展示数据的方法。根据应用逻辑上下文的不同,视图决定了怎样展示数据。比如,在加拿大,一个公民可以选择使用短格式的出生证明或者是较长格式的出生证明。两种出生证明文档都包括了一样的关键信息(Model),但是细节程度不同(View)。在Backbone里,视图提供了一个“窗口”来查看一个模型中的数据、协助监听在界面上的用户交互或者数据模型上的变化,从而触发数据显示的更新。
下面的是在网页中显示出生证明数据的例子。
<div id="certificate"></div> <script type="text/javascript">
CertificateView = Backbone.View.extend({
initialize: function () {
this.render();
},
render: function () {
$(this.el).html("<h1>Guy Incognito</h1><p>DOB: March 2, 1967</p>");
}
});
var certificate_view = new CertificateView({
el: $("#certificate")
});
</script>
在上述代码中,声明了一个 CertificateView 类,作为出生证明的视图实例。它同样使用了backbone的extend方法来扩展了一个定制的视图结构,也就是出生证明这个结构(使用extend方法就跟上一节中的扩展“模型”一样)。这个定制的视图包含了两个方法:
initialize 方法 —— 当一个该视图结构的实例被创建时,这个方法被执行。在上述代码示例中,initialize要做的就是立即触发render函数来处理数据显示。
render方法 —— 调整DOM节点里面的内容,达到显示数据的目的。
在backbone里,所有的“视图”都不可避免的要跟DOM树操作打交道。在上述代码里,我们实例化视图时,传入了一个需要显示数据的DOM节点。如果你没有传入任何DOM节点,那么backbone将会处理页面上所有的div节点。
视图模板 View Template
上一节的代码有一个潜在的问题:在JavaScript代码里出现了生成HTML代码的逻辑。因此,我们需要使用“视图模板”来分离耦合的处理逻辑。注意,Backbone里的 View 并不包含template本身,它只提供view的控制逻辑,而具体生成template的功能是靠其依赖库 underscore 的 .template() 方法实现的。
具体的说,我们把生成HTML的逻辑从视图层的render函数中移了出来,把它放在一个<script>标签下。为了防止浏览器把它当作真正的JavaScript代码去处理它,<script>的type属性被设置成 text/template (而不是默认的 text/javascript)。如果不重新声明默认的type属性,那么浏览器就会用JS的引擎去处理那里面的内容,而由于视图模板常常是HTML代码段,所以通常会抛出JS语句解析错误。
<div id="certificate"></div>
<script type="text/template" id="tpl-certificate">
< h1 > <%= name %> < /h1>
<p> DOB: <%= dob %> </p >
</script>
<script type="text/javascript">
CertificateView = Backbone.View.extend({
template: _.template($('#tpl-certificate').html()),
initialize: function () {
this.render();
},
render: function () {
var templateArgs = {
name: "Guy Incognito",
dob: "March 2, 1967"
};
$(this.el).html(this.template(templateArgs));
}
});
var certificate_view = new CertificateView({
el: $("#certificate")
});
</script>
在上述代码中,name和date被当作视图模板的参数变量。在模板里使用变量时,需要加上<% 和 %>标签。如果需要输出变量,则需要使用 <%= 标签,跟JSP的语法一样。
在视图中使用模板需要注意两步:第一步,视图逻辑必须知道采用哪一个模板来渲染数据;第二步,使用模板时需要传入变量参数。
我们使用了jQuery的 .html() 函数来获取<script>标签下的模板内容。 接着,我们又使用了 underscore 的 .template() 函数 根据参数变量和模板原文 来组合生成最终要显示的HTML代码。
现在,使用 实例名.render() 就可以实现数据显示的工作了。 在render函数里,首先声明了需要传入模板的参数变量(大多数情况下,这个需要从模型层获取),接着使用template函数生成HTML代码,最后使用 jQuery.html()更改DOM节点中的内容。
集合 Collection
在Backbone里,集合是模型Model的有序组合,我们可以在集合上绑定 "change" 事件,从而当集合中的模型发生变化时获得通知,集合也可以监听 "add" 和 “remove" 事件, 从服务器更新。同时,你也可以使用 Underscore 提供的方法(例如 forEach, filter, sortBy等等)。
你可以通过扩展 Backbone.Collection 创建一个 集合。
var Library = Backbone.Collection.extend({
model: Book
});
尽管使用集合有开销,为什么还要使用集合而不使用JavaScript内置的数组? 首先,通过扩展Backbone.Collection的方式来创建对象有利于“文档化”你的代码。例如,在下面的例子中,集合类 Team 定义了 Stooge 作为它的数据模型类型,所以当你书写代码时,你就知道backbone在处理该集合时是依照怎样的数据类型结构。 当然,使用集合更重要的原因是,集合提供了一套强大的命令让你 获取/操纵 里面的内容,因此你不需要自己写对应的方法。
var Stooge = Backbone.Model.extend({
defaults: {
'name': '',
'power': ''
}
});
var Team = BackBone.Collection.extend({
model: Stooge
});
var larry = new Stooge({
name: 'Larry',
power: 'Baldness'
});
var moe = new Stooge({
name: 'Moe',
power: 'All Powers'
});
var curly = new Stooge({
name: 'Curly',
power: 'Hair'
});
var threeStooges = new Team([larry, curly, moe]);
当集合中包含的“模型”发生数据变化时,集合会激发相应的事件,因此你可以捕获那些事件从而完成视图上的更新。
同步 Sync
在backbone中,使用 Sync 类(Backbone.sync)完成与服务器端的数据模型的读取与存储。 通常情况下,你可以用 jQuery的 .ajax 方法来发送和接收 JSON 格式的数据。如果想采用不同的持久化方案,比如 WebSockets, XML, 或 Local Storage,我们可以重载该函数。
Backbone.sync 的语法为 sync(method, model, [optional callback])。
method – CRUD 方法 ("create", "read", "update", 或 "delete") create对应POST,read 对应GET。
model – 要被保存的模型(或要被读取的集合)
与Sync配套使用最常见的方法是 model.save([attributes], [options])。 model.save 通过委托 Backbone.sync 保存数据模型到服务器端。 attributes 散列表 (在 set) 应当包含想要改变的属性,不涉及的键不会被修改。 如果模型含有 validate 方法,并且验证失败,模型不会保存。 如果模型在服务器端不存在, save将采用 "create" (HTTP POST) 方法, 如果模型已经在服务器存在,保存将采用 "update" (HTTP PUT) 方法.
在下面的示例,我们在client端生成一个图书的数据模型,并把它sync到服务器端。
Backbone.sync = function (method, model) {
alert(method + ": " + JSON.stringify(model));
model.id = 1;
}; var book = new Backbone.Model({
title: "The Rough Riders",
author: "Theodore Roosevelt"
}); book.save(); 由于模型在服务器端没有,所以这一次调用,sync会使用 "create" 请求 book.save({
author: "Teddy"
}); 这一次服务器端有了,所以sync会使用 "update"请求。注意,这只更新了模型的部分属性。没有涉及的属性在服务器端不会被修改。
路由 Router
web应用程序通常需要为应用的重要位置提供可链接,可收藏,可分享的 URLs。 越来越多的web程序开始使用 锚点(hash)片段(#page)来提供这种可收藏,可分享的链接。 同时随着 History API 的到来,锚点已经可以用于处理标准 URLs (/page)。 Backbone.Router 为客户端路由提供了许多方法,并能连接到指定的动作(actions)和事件(events)。 对于不支持 History API 的旧浏览器,路由提供了优雅的回调函数并可以透明的进行 URL 片段的转换。
看上去,在 Backbone 里似乎缺少了 Controller 类型,实际上,每一个“路由”都可以被看作是从 Controller 上扩展的。 传统意义上的 Controller 是有问题的,因为它融合了两种功能,第一就是根据 View 来控制 Model,第二就是控制用户在不同的 View 之间切换。而 Backbone 通过把 Router 单独剥离出来,就优雅地分离了 用户界面 和 操纵Model。
那为什么不给 controller 建立单独的类呢?根据MVC定义,Controller类应该是你程序主干逻辑的实现。在backbone里,由于程序的具体处理细节都从 controller 层分离出去了(比如 在Model内部处理数据,由Router处理用户request等等),因此你不太需要单独的一个 Controller 类来处理程序的主干逻辑。
下面这个例子显示了如何设置一个路由,该路由需要处理的URL诸如 #/certificates/123 或者 #/certificates/mycertificatename,然后该路由依据certificateID或者certificatename 新建一个 View (new CertificateView)。 下面这个简单的代码并没有依据 ID 处理CertificateView,但是实际开发中,你可能需要依据ID来 读取/处理 模型。
var MyRouter = Backbone.Router.extend({
routes: {
"/certificates/:id": "getCertificate",
},
getCertificate: function (id) {
new CertificateView({
el: $("#certificate")
});
}
});
var router = new MyRouter;
Backbone.history.start();
参考资料:
Backbone中文文档 http://www.csser.com/tools/backbone/
什么是 Backbone.js的更多相关文章
- MVC、MVP、MVVM、Angular.js、Knockout.js、Backbone.js、React.js、Ember.js、Avalon.js、Vue.js 概念摘录
注:文章内容都是摘录性文字,自己阅读的一些笔记,方便日后查看. MVC MVC(Model-View-Controller),M 是指业务模型,V 是指用户界面,C 则是控制器,使用 MVC 的目的是 ...
- Backbone.js应用基础
前言: Backbone.js是一款JavaScript MVC应用框架,强制依赖于一个实用型js库underscore.js,非强制依赖于jquery:其主要组件有模型,视图,集合,路由:与后台的交 ...
- 我对Backbone.js的一些认识
backbone.js已经不是当前最流行的前端框架了,但是对于我而言,依然具有比较好的学习价值.虽然目前来说,react,vue等mvvm框架非常火热,但是感觉自身还不到去使用这种框架的层次.这些技术 ...
- Backbone.js学习之Backbone.View(视图)
Backbone.js为复杂WEB应用程序提供模型(models).集合(collections).视图(views)的结构.其中模型用于绑定键值数据和自定义事件:集合附有可枚举函数的丰富API: 视 ...
- 前端mvc框架backbone.js入门[转]
原文地址:http://www.cnblogs.com/zhjh256/p/6083618.html 关于backbone.js的优缺点,这里就不详谈了,网上关于这方面的讨论很多了,而且各种框架之所以 ...
- Backbone.js
Backbone.js是一套JavaScript框架與RESTful JSON的應用程式介面.也是一套大致上符合MVC架構的編程範型.Backbone.js以輕量為特色,只需依賴一套Javascrip ...
- 用Backbone.js教程系列的链接
整理了一下用Backbone.js系列教程链接. Backbone.js入门教程 用Backbone.js创建一个联系人管理系统(一) 用Backbone.js创建一个联系人管理系统(二) 用Back ...
- 用Backbone.js创建一个联系人管理系统(五)
原文: Build a Contacts Manager Using Backbone.js: Part 5 这是这系列教程最后一部分了. 之前所有的增删改都在前端完成. 这部分我们要把Contact ...
- 用Backbone.js创建一个联系人管理系统(四)
原文: Build a Contacts Manager Using Backbone.js: Part 4 这一系列教程的第四部分,教我们如何完成对已经存在的Contacts进行编辑和保存. 本教程 ...
- 用Backbone.js创建一个联系人管理系统(三)
原文: Build a Contacts Manager Using Backbone.js: Part 3 欢迎回到这系列的教程,关注使用Backbone.js构建应用程序. 如果你还没看过第一,二 ...
随机推荐
- videojs做直播、弹幕
从上一年开始,我们开始接触直播,现在直播成本真的很低,很多CDN供应商都有提供,本文只是大概讲述播放器这个话题. 开始调研 播放格式,我挑了三种.分别是HLS,RTMP,HTTP-FLV. 下面简单说 ...
- 非交互式shell脚本案例-实现自主从oracle数据库获取相关数据,并在制定目录生成相应规则的文件脚本
get_task_id 脚本内容 #!/usr/bin/expect#配置登陆数据库的端口set port 22#配置登陆数据库的ip地址set oracleip 10.0.4.41#配置数据库实例名 ...
- PlantUML——3.Graphviz的安装
官网:http://www.graphviz.org/Home.php 由于plantuml使用Graphviz来生成相关图形(只有序列图可以不依赖它),其它图形都需要, 因此得安装它,否则生成图 ...
- POJ 1218 THE DRUNK JAILER(类开灯问题,完全平方数)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2188 题目大意:n为5-100之间的一个数,代表有多少间牢房,刚开始所有房间打开,第一轮2的倍数的房间 ...
- restful的设计风格
网络应用程序,分为前端和后端两个部分.当前的发展趋势,就是前端设备层出不穷(手机.平板.桌面电脑.其他专用设备......). 因此,必须有一种统一的机制,方便不同的前端设备与后端进行通信.这导致AP ...
- 深度学习方法(十二):卷积神经网络结构变化——Spatial Transformer Networks
欢迎转载,转载请注明:本文出自Bin的专栏blog.csdn.net/xbinworld. 技术交流QQ群:433250724,欢迎对算法.机器学习技术感兴趣的同学加入. 今天具体介绍一个Google ...
- Qt5.4 webview 不能打开网址
在使用Qwebview浏览器时不能打开网络地址,并报下面的错误 Starting E:\WorkSpace\QtWorkSpace\build-webTest-Desktop_Qt_5_4_2_MSV ...
- ADO.NET怎删改+vs 2013 C#
一.删除 string constr = "server=.;database=test;uid=sa;pwd=sa"; SqlConnection myco ...
- 2017-2018-1 20179202《Linux内核原理与分析》第六周作业
一.系统调用实验(下): 1.编辑 menu 中的 text.c 文件,给MenuOS增加 rename 和 rename_asm 命令: make rootf 打开 menu 镜像,可以看到Menu ...
- [Codeforces50C]Happy Farm 5 凸包
大致题意: 平面上有n个整数点,问你最少经过多少步能够将所有点严格包围. 将点严格包围要求你走的路径完全包围给出的点且不能有点在路径上 你只能走整数点,且方向只有上下左右左上右下等8个方向,每次移动一 ...