什麼是Backbone.js?
Backbone.js是十大JS框架之首,Backbone.js 是一個重量級js MVC 應用框架,也是js MVC框架的鼻祖。它透過Models資料模型進行鍵值綁定及custom事件處理,透過模型集合器Collections提供一套豐富的API用於枚舉功能,透過視圖Views來進行事件處理及與現有的Application透過JSON介面進行交互。
簡而言之,Backbone是實作了web前端MVC模式的js函式庫
什麼是MVC?
MVC:後端伺服器首先(過程1)透過瀏覽器取得頁面位址,對網址進行解析,得到視圖View給它的一個網址,然後透過控制器controller進行解析,然後去找對應的資料(過程2),找到資料後,再將資料Model回傳給控制器(流程3),控制器controller再對資料進行加工,最後回到視圖(流程4),也就是更新視圖View。這種結構在後端是非常清晰且易實現的
Backbone中MVC的機制
Backbone將資料呈現為模型, 你可以創建模型、對模型進行驗證和銷毀,甚至將它保存到伺服器。 當UI的變化引起模型屬性改變時,模型會觸發"change"事件; 所有顯示模型資料的視圖都會接收到該事件的通知,繼而視圖重新渲染。 你無需尋找DOM來搜尋指定id的元素去手動更新HTML。 — 當模型改變了,視圖就會自動變更。 ———百度百科
模式:一種解決問題的通用方法
—設計模式:工廠模式、適配器模式與觀察者模式
—框架模式:MVC、MVP、MVVM
控制器:透過控制器來連接視圖與模型。
MVC模式的想法:
就是把模型與視圖分離,透過控制器連接他們
伺服器端MVC模式非常容易實現
Model:模型即數據,模型 是所有 js 應用程式的核心,包括交互數據及相關的大量邏輯: 轉換、驗證、計算屬性和存取控制。你可以用特定的方法擴充 Backbone.Model
View:即你在頁面上所能看到的視圖。每一個單一的資料模型對應一個視圖View
web頁面本身就是一個很大的view,不太容易做到分離操作,backbone.js適合複雜的大型開發,並為我們解決了這些難題
backbone的模組
backbone有以下幾個模組:
集合器Collection是對單獨的資料模型進行統一控制
直接建立物件
Backbone依賴Underscore.js, DOM 處理依賴於Backbone.View 和jQuery ,因此,在引入Backbone.js之前,Underscore.js必須在它之前引入,而jQuery也最好一併引入,最後再引入Backbone.js
<head lang="en"> <meta charset="UTF-8"> <title></title> <script src = "jquery-2.0.3.min.js"></script> <script src = "underscore-min.js"></script> <script src = "backbone.js"></script> </head> <body> var model = new Backbone.Model(); var col = new Backbone.Collection(); var view = new Backbone.View(); </body>
new後面是一個建構函數,而Backbone是作為建構函數的命名空間來使用的
Model模組
Backbone.Model.extend(properties, [classProperties])
Backbone透過extend來擴充實例方法與靜態方法:
<script type="text/javascript"> //extend接收的第一个参数是json格式的字符串,用来扩展实例方法 //第二个参数也是json格式的字符串,用来扩展静态方法 var M = Backbone.Model.extend({ abc : function(){ //实例方法 alert("hello backbone"); } },{ def : function(){ //静态方法 alert("hi"); } }); var model = new M; model.abc();//实例方法要用实例对象来访问 M.def();//静态方法直接挂载到了构造函数上,可以通过构造函数来直接访问 </script>
靜態方法其實就是多了一個命名空間。以上是為建構函式加入實例方法和靜態方法
var M = Backbone.Model.extend({})
透過extend來為模型的建構子擴充方法,M就是擴充之後的建構子
繼承
<script type="text/javascript"> //继承 var Mod = backbone.Model.extend({ abc : function(){ alert(123); } }); var ChildMod = Mod.extend(); var model = new ChildMod; model.abc();//子类继承了父类的方法 </script>
Backbone源码结构
1: (function() {
2: Backbone.Events // 自定义事件
3: Backbone.Model // 模型构造函数和原型扩展
4: Backbone.Collection // 集合构造函数和原型扩展
5: Backbone.Router // 路由配置器构造函数和原型扩展
6: Backbone.History // 路由器构造函数和原型扩展
7: Backbone.View // 视图构造函数和原型扩展
8: Backbone.sync // 异步请求工具方法
9: var extend = function (protoProps, classProps) { ... } // 自扩展函数
10: Backbone.Model.extend = Backbone.Collection.extend = Backbone.Router.extend = Backbone.View.extend = extend; // 自扩展方法
11: }).call(this);
JS MVC职责划分
M 模型
业务模型:业务逻辑、流程、状态、规则
(核心)数据模型:业务数据、数据校验、增删改查(AJAX)
V 视图
(核心)视图:定义、管理、配置
模板:定义、配置、管理
组件:定义、配置、管理
(核心)用户事件配置、管理
用户输入校验、配置、管理
C 控制器/分发器
(核心)事件分发、模型分发、视图分发
不做数据处理、业务处理,即业务无关
扩展:权限控制、异常处理等
C是JSMVC框架的核心,实现集中式配置和管理,可以有多个控制器
工具库
主要是异步请求、DOM操作,可以依赖于jQuery等
Model指的是一条一条的数据,而集合Collection指的是对Model中的多条数据进行管理。
模型 Model
我们用Backbone.Model表示应用中所有数据,models中的数据可以创建、校验、销毁和保存到服务端。
对象赋值的方法
1、直接定义,设置默认值
Trigkit = Backbone.Model.extend({ initialize : function () { alert('hi!'); }, defaults:{ age : '22', profession : 'coder' } }); var coder = new Trigkit; alert(coder.get('age'));//22
2、 赋值时定义
<script type="text/javascript"> Trigkit = Backbone.Model.extend({ initialize : function () { alert('hi!'); } }); var t = new Trigkit; t.set({name :'huang',age : '10'}); alert(t.get('name')); </script>
对象中的方法
<script type="text/javascript" src="Underscore.js"></script> <script type="text/javascript" src="backbone-1.1.2.js"></script> <script type="text/javascript"> var Trigkit4 = Backbone.Model.extend({ initialize : function () { alert("hello world!"); }, defaults : { name : 'zhangsan', age : 21 }, aboutMe: function () { return '我叫' + this.get('name') + ',今年' + this.get('age') + '岁'; } }); var t = new Trigkit4; alert(t.aboutMe()); </script>
当模型实例化时,他的initialize方法可以接受任意实例参数,其工作原理是backbone模型本身就是构造函数,所以可以使用new生成实例:
var User = Backbone.Model.extend({ initialize: function (name) { this.set({name: name}); } }); var user = new User('trigkit4'); alert(user.get('name'), 'trigkit4');//trigkit4
看下backbone的源码:
var Model = Backbone.Model = function(attributes, options) { var attrs = attributes || {}; options || (options = {}); this.cid = _.uniqueId('c'); this.attributes = {}; if (options.collection) this.collection = options.collection; if (options.parse) attrs = this.parse(attrs, options) || {}; attrs = _.defaults({}, attrs, _.result(this, 'defaults')); this.set(attrs, options); this.changed = {}; this.initialize.apply(this, arguments); }; initialize: function(){},//initialize是默认的空函数
Model 的事件绑定
为了能及时更新view,我们需要通过事件绑定机制来处理和响应用户事件:
<script type="text/javascript"> var Task = Backbone.Model.extend({ initialize: function () { this.on("change:name", function (model) { alert("my name is : " + model.get("name")); }); } }); var task = new Task({ name:"oldname", state:"working"}); task.set({name:"trigkit"}); // object.on(event, callback, [context]) </script> </head>
关于事件绑定,有on,off,trigger,once,listenTo,stopListening,listenToOnce等方法,具体参照:http://documentcloud.github.io/backbone/#Events
集合 Collection
Backbone.Collection就是一个Model对象的有序集合。因为Model是一条数据记录,也就是说,Collection相当于是一个数据集。具有增加元素,删除元素,获取长度,排序,比较等一系列工具方法,说白了就是一个保存models的集合类。
<script type="text/javascript"> var Book = Backbone.Model.extend({ defaults : { title:'default' }, initialize: function(){ alert('hello backbone!');//弹出3次 } }); BookShelf = Backbone.Collection.extend({ model : Book }); var book1 = new Book({title : 'book1'}); var book2 = new Book({title : 'book2'}); var book3 = new Book({title : 'book3'}); //var bookShelf = new BookShelf([book1, book2, book3]); //注意这里面是数组,或者使用add var bookShelf = new BookShelf; bookShelf.add(book1); bookShelf.add(book2); bookShelf.add(book3); bookShelf.remove(book3); //基于underscore这个js库,还可以使用each的方法获取collection中的数据 bookShelf.each(function(book){ alert(book.get('title')); }); </script>
collection.model覆盖此属性来指定集合中包含的模型类。可以传入原始属性对象(和数组)来 add, create,和 reset,传入的属性会被自动转换为适合的模型类型。
视图 View
Backbone.View中可以绑定dom元素和客户端事件。页面中的html就是通过views的render方法渲染出来的,当新建一个view的时候通过要传进一个model作为数据
view.$el:一个视图元素的缓存jQuery对象。 一个简单的引用,而不是重新包装的DOM元素。
一个简单的View:
<head> <meta charset="UTF-8"> <title>Document</title> <script type="text/javascript" src="jquery-1.9.1.min.js"></script> <script type="text/javascript" src="Underscore.js"></script> <script type="text/javascript" src="backbone-1.1.2.js"></script> <script type="text/javascript"> var TestView = Backbone.View.extend({ //创建一个view,其实就是一个HTML的DOM节点 initialize: function() { this.render(); }, render: function() { // 渲染方法 this.$el.html('Hello World'); //this.el就是HTML节点,通过jQuery的html方法填充内容 return this; } }); $(function () { var test = new TestView({el: $('#body')});// 以目标节点为el参数,创建一个view的实例,render函数将会被自动调用并将渲染结果填充到el中 //test.render(); // 如果没在 initialize 里调用 render 的话,就需要在这里调用一次 }); </script> </head> <body> <div id="body"></div> </body>
elview.el所有的视图都拥有一个 DOM 元素(el 属性),即使该元素仍未插入页面中去。 视图可以在任何时候渲染,然后一次性插入 DOM 中去,这样能尽量减少 reflows 和 repaints 从而获得高性能的 UI 渲染。 this.el 可以从视图的 tagName, className, id 和 attributes 创建,如果都未指定,el 会是一个空 div。 --官网
扩展方法 extend
模型、集合、视图、路由器都有一个extend方法,用于扩展原型属性和静态属性,创建自定义的模型、集合、视图、路由器类。
Backbone.Model.extend Backbone.Model.extend(properties, [classProperties])
要创建自己的 Model 类,你可以扩展 Backbone.Model 并提供实例 properties(属性) , 以及可选的可以直接注册到构造函数的classProperties(类属性)。
Backbone.View.extend Backbone.View.extend(properties, [classProperties])
开始创建自定义的视图类。 通常我们需要重载 render 函数,声明 events, 以及通过 tagName, className, 或 id 为视图指定根元素。 Backbone.View通过绑定视图的 render 函数到模型的 "change" 事件 — 模型数据会即时的显示在 UI 中。
Backbone.Collection.extend Backbone.Collection.extend(properties, [classProperties])
通过扩展 Backbone.Collection 创建一个 Collection 类。实例属性参数 properties 以及 类属性参数 classProperties 会被直接注册到集合的构造函数。
Backbone.Router.extend Backbone.Router.extend(properties, [classProperties])
开始创建一个自定义的路由类。当匹配了 URL 片段便执行定义的动作,并可以通过 routes 定义路由动作键值对。
Router与controller
controller是Backbone 0.5以前的叫法,现在改名叫Router了。
Backbone.Router 为客户端路由提供了许多方法,并能连接到指定的动作(actions)和事件(events)。
页面加载期间,当应用已经创建了所有的路由,需要调用 Backbone.history.start()
查看下面示例:
<script type="text/javascript"> var AppRouter = Backbone.Router.extend({ routes: { "index" : "index", "task/:id": "task", "*acts": "tasklist" }, index: function() { alert("index"); }, tasklist: function(action) { alert(action); }, task: function(id) { alert(id); } }); var app = new AppRouter; Backbone.history.start(); </script>
在浏览器里打开页面后,在url的html后面依次加上:
#/index #/task/1 #/test/xxxx
将分别弹出出:index, 1, test/xxxx
这就是Router的功能。