
正文
Backbone——数据驱动UI的js开发模式
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10826074.html
一:Backbone是什么——JS的MVC框架
Backbone基于underscore,依赖jquery或zepto,它是一款web前端开发的 javascript MVC框架, 使我们可以像高级语言一样 定义类、类属性及方法,更好的组织代码并按框架提供的数据逻辑分离方法, 减少代码混乱。
二:Backbone有什么——数据、视图
1)backbone的3大核心模块
模型:Backbone.Model,一个数据模型
集合:Backbone.Collection,数据模型的一个集合
视图:Backbone.View,数据处理,注意它并非我们传统认知中的页面模版
模型、集合负责保存 、管理数据,视图负责响应数据变化并呈现。
模型用于绑定键值数据和自定义事件;集合附有可枚举函数的丰富API; 视图可以声明事件处理函数,并通过RESRful JSON接口连接到应用程序。
2)模型
Model这个模块可以让我们用来定义一些纯数据管理的类,大部分情况下,这些类就是我们所要开发的功能对应的业务实体。
用Model定义的类能够为我们提供直接修改和获取业务实体数据属性的功能,也能够通过简单明了的api直接与服务器进行数据同步,比如前面用到的fetch,save,还有没用到的destroy等;
通过Backbone,你可以将数据呈现为 Model, 你可以对模型进行创建,验证和销毁,以及将它保存到服务器。
3)视图
View这个模块可以让我们来封装页面中某个独立完整部分的UI功能,它往往会与Model模块进行关联,并且配合模板一起完成UI的更新,通过监听Model实例的变化来重新渲染html,通过自身注册的事件将UI的变化同步到Model实例,它就像一个控制器,同步数据与界面UI的实时变化。
任何时候只要UI事件引起模型内的属性变化,模型会触发 "change" 事件,所有显示模型数据的 Views 会接收到该事件的通知,继而视图重新渲染。
你无需查找DOM来搜索指定 id 的元素去手动更新HTML,当模型改变了,视图便会自动变化。
Backbone的底层还有一个sync模块,封装了数据同步时异步请求管理的功能:
backbone的Model模块提供的fetch, save, destroy方法,和Collection模块的fetch方法,都会发送异步请求,与后端服务进行交互。
然后所有这些有异步请求操作的方法,都依赖于sync这个模块,来完成请求头和请求数据的封装,以及请求回调的处理。
以View为核心进行web前端开发的思想:
在Backbone里,一个View通常都由以下内容组成:
el
(代表web页面上的一块区域)
template
(代表模板)
model/collection
(代表要渲染进模板的数据)
除此之外就是各种页面元素的事件绑定和处理以及监听其他View或Model/Collection的事件。
一个Backbone的View实例就代表了web页面上的一块区域,它 全权负责这块区域,包括如何渲染它,如何处理这块区域内的事件响应,根据其他对象的事件来更改这块区域的渲染 ,等等等等。
一个完整的web页面恰恰可以看成是一个个的view组成 的,所以,View可以说是使用Backbone开发绝对的核心。
4)集合
Collection这个模块可以指定存储某种Model的多个实例。
它提供有简单的api比如fetch,create方法来直接同步服务器的数据。
如果说Model跟View的关系,是把数据与UI进行解耦,那么Collection跟View,就是把数据列表与UI进行解耦 .
Model实例仅仅是作用于单条数据的功能,而Collection实例可以作用于多条数据的功能,就跟Model可以被直接关联到View一样, Collection实例也能直接通过collection属性,在创建View实例的时候,传递给View ;
在Collection内的model元素发生增删改的时候,通知View实例去重新渲染html;在用户与View实例发生交互的时候,View主动去调整Collection里面的内容;View层充当控制器的作用,实时同步UI与Collection之间的变化。
Collection的作用,确实跟Model的作用差不多,理解它的方法,完全可以类比Model。
三:Backbone的事件体系——Backbone.Events
Model,View以及Collection三个模块都继承了Events,使得它们的实例都拥有直接进行事件管理的能力。
Events模块除了让Model等模块的实例拥有强大的自定义事件管理,同时它还提供了一套内置的事件体系,这套事件体系其实就是前面数据驱动的关键:
当View层的实例,与之相关联的Model实例和Collection实例触发了这些事件,都可以直接通知View层实例执行相应的事件回调,我们所要做的只需要在View层实例初始化的时候,注册好跟它关联的Model实例或Collection实例的事件监听即可。
前面这些能够解释为什么当Model或Collection发生变化的时候,为什么能够引起View层的变化。但是还有一个方面没有说清楚,就是由于用户与浏览器交互导致的View层的变化,如何同步到数据。
其实,跟平常使用jquery绑定各类键鼠事件,然后在事件监听里面直接去更新关联的Model或Collection实例没有区别: 为VIew实例注册事件,并将事件回调设置为自定义的事件处理函数即可 。
四: Backbone官方文档摘录
1、Backbone.Events(事件)
Events
是一个
可以融合到任何对象的模块
, 给予 对象绑定和触发自定义事件的能力。
Events 是一个 可以融合到任何对象的模块 , 给予 对象绑定和触发自定义事件的能力。
on方法:
object.on(event, callback, [context])
别名: bind
我们约定使用 冒号来为事件添加 命名空间 俗成地使用冒号来命名某个特定属性的变化: "poll:start" , 或 "change:selection"
listenTo方法:
object.listenTo(other, event, callback)
让
object
监听
另一个(other)
对象上的一个特定事件。
2、Backbone.Model(模型)
Models(模型)
是包括数据交互及与其相关的大量逻辑: 转换、验证、计算属性和访问控制。
可以用特定的方法扩展
Backbone.Model去创建你自己的Model,重写或添加逻辑。
extend方法:
Backbone.Model.extend(properties, [classProperties])
要创建自己的
Model
类,你可以扩展
Backbone.Model
并提供实例
properties(属性)
, 以及可选的可以直接注册到构造函数的
classProperties(类属性)
。
extend 可以正确的设置原型链,因此通过 extend 创建的子类 (subclasses) 也可以被深度扩展。
父类函数的调用:Javascript没有提供一种直接调用父类的方式,如果你想调用父对象的实现,这时需要明确的在子类同名函数中调用原型链中 上层定义的同名函数:
Backbone.Model.prototype.父类函数.apply(this, arguments);
constructor / initialize方法:
new Model([attributes], [options])
当创建model实例时,可以传入 属性 (
attributes
)初始值,这些值会被 set (设置)到 model。 如果定义了
initialize
函数,该函数会在model创建后执行。
get方法:
model.get(attribute)
从当前model中获取当前属性(attributes)值,比如:
note.get("title")
set方法:
model.set(attributes, [options])
向model设置一个或多个hash属性(attributes)。如果任何一个属性改变了model的状态,在不传入 {silent: true} 选项参数的情况下,会触发
"change"
事件,更改特定属性的事件也会触发。
defaults属性:
model.defaults or model.defaults()
defaults
散列(或函数)用于为模型指定默认属性。 创建模型实例时,任何未指定的属性会被设置为其默认值。
sync方法:
model.sync(method, model, [options])
使用 Backbone.sync 可以将一个模型的状态持续发送到服务器,
可以自定义行为覆盖【可以自定义数据传输与响应逻辑】
。
save方法:
model.save([attributes], [options])
通过委托给Backbone.sync,保存模型到数据库(或替代持久化层)。 如果验证成功,返回jqXHR,否则为
false
。
destroy方法:
model.destroy([options])
通过委托给Backbone.sync,保存模型到数据库(或替代持久化层)。 通过委托一个HTTP
DELETE
请求给Backbone.sync破坏服务器上的模型。 返回一个jqXHR对象, 或者如果模型isNew,那么返回
false
。
validate方法:
model.validate(attributes, options)
这种方法是未定义的, 如果您有任何可以在JavaScript中执行的代码 并且我们鼓励你用你自定义验证逻辑覆盖它 。 默认情况下
validate
在
save
之前调用, 但如果传递了
{validate:true}
,也可以在
set
之前调用。
parse方法:
model.parse(response, options)
parse
会在通过 fetch 从服务器返回模型数据
3、Backbone.Collection(集合)
集合是模型的有序组合,我们可以在集合上绑定
"change"
事件,从而当集合中的模型发生变化时
fetch
(获得)通知,集合也可以监听
"add"
和
"remove"
事件, 从服务器更新,并能使用 Underscore.js 提供的集合操作方法。
extend方法:
Backbone.Collection.extend(properties, [classProperties])
通过扩展
Backbone.Collection
创建一个自定义的
Collection
类。
model属性:
collection.model
覆盖此属性
来指定集合中包含的元素属于什么model的实例
。
其他集合操作函数:参照 Underscore集合操作API:
4、Backbone.Router(路由)
Backbone.Router
为客户端路由提供了许多方法,并能连接到指定的动作(actions)和事件(events),对于不支持 History API 的旧浏览器,路由提供了优雅的回调函数并可以透明的进行 URL 片段的转换。
extend方法:
Backbone.Router.extend(properties, [classProperties])
创建一个自定义的路由类。
var Workspace = Backbone.Router.extend({
routes: {
"help": "help", // help路由动作的响应函数
"search/:query": "search", //search路由动作的响应函数
"search/:query/p:page": "search" //search路由动作的响应函数 },
help: function() {
在路由响应函数中进行跳转。
},
search: function(query, page) {
...
}
});
其他路由跳转、新增方法:
5、Backbone.history
History 作为全局路由服务用于处理 hashchange 事件或 pushState ,匹配适合的路由,并触发回调函数。 我们不需要自己去做这些事情 — 如果使用带有键值对的 路由, Backbone.history 会被自动创建。
start
Backbone.history.start([options])
当所有的 Routers 创建并设置完毕,调用
Backbone.history.start()
开始监控
hashchange
事件并分配路由。
6、Backbone.sync(同步)
Backbone.sync
是 Backbone 每次向服务器读取或保存模型时都要调用执行的函数。
默认情况下,它使用
jQuery.ajax
方法发送 RESTful json 请求,并且返回一个 jqXHR。 如果想采用不同的持久化方案,比如 WebSockets, XML, 或 Local Storage,我们可以重载该函数。
Backbone.sync 的语法为 sync(method, model, [options]) 。
- method – CRUD 方法 ( "create" , "read" , "update" , or "delete" )
- model – 要被保存的模型(或要被读取的集合)
- options – 成功和失败的回调函数,以及所有 jQuery 请求支持的选项
7、Backbone.View(视图)
模型变化时, 每一个都可以独立地进行更新, 而不必重新绘制该页面。
我们再也不必钻进 JSON 对象中,查找 DOM 元素,手动更新 HTML 了,通过绑定视图的 render 函数到模型的 "change" 事件 — 模型数据会即时的显示在 UI 中。
extend方法:
Backbone.View.extend(properties, [classProperties])
开始创建自定义的视图类。 通常我们需要重载 render 函数,声明 events, 以及通过
tagName
,
className
, 或
id
为视图指定根元素。
var DocumentRow = Backbone.View.extend({
tagName: "li",
className: "document-row",
events: {
"click .icon": "open",
"click .button.edit": "openEditDialog",
"click .button.delete": "destroy"
},
initialize: function() {
this.listenTo(this.model, "change", this.render);
},
render: function() {
...
}
});
constructor / initialize方法:
new View([options])
有几个特殊的选项, 如果传入,则直接注册到视图中去:
model
,
collection
,
el
,
id
,
className
,
tagName
,
attributes
和
events
。 如果视图定义了一个
initialize
初始化函数, 首先创建视图时,它会立刻被调用。 如果希望创建一个指向 DOM 中已存在的元素的视图,传入该元素作为选项:
new View({el: existingElement})
。
new DocumentRow({
model: doc,//创建视图实例,将模型实例作为参数传递进去作为视图数据
id: "document-row-" + doc.id
});
el属性:
view.el
所有的视图都拥有一个 DOM 元素(
el
属性),即使该元素仍未插入页面中去。
$el属性:
view.$el
一个view实例对应的jQuery对象,可以通过该对象调用jQuery相关api,进行dom操作
。例如:
view.$el.show(); listView.$el.append(itemView.el);
$ (jQuery)方法:
view.$(selector)
如果页面中引入了 jQuery.js,每个view实例都将拥有
$
函数,可以在视图元素查询作用域内运行。
template属性:
view.template([data])
我们可以 使用underscore定义的模版 ,方便地渲染我们的view视图。
template: _.template(一个template定义)
render方法:
view.render()
render
默认实现是没有操作的。 重载本函数可以实现
用模型数据渲染视图的template模板
,然后插入到本view实例在dom中的位置。在
render
函数的末尾
return this
以开启链式调用。
render: function() {
this.$el.html(this.template(this.model.attributes));//
return this;
}
上面代码解释:
this.$el:获取本view实例对应的jQuery对象进行dom操作
this.$el.html:操作dom元素的值
this.template(this.model.attributes):使用本view实例的model的数据,渲染本view实例的template







