1. 程式人生 > >從豆瓣說和Backbone.js說開去

從豆瓣說和Backbone.js說開去

簡而言之,Backbone.js是一個可以在前端組織MVC的javascript框架。

寫的Javascript程式碼一旦多起來,沒有一個好的組織,那就會像噩夢一樣。

Backbone提供了Models, Collections, Views。Models 用來建立資料,校驗資料,繫結事件,儲存資料到伺服器端;Collections 包含你建立的 functions;Views 用來展示資料。如此這般,在前端也做到了資料和顯示分離。

Backbone依賴於Underscore.js,這是一個有很多常用函式的js檔案(很好用)

下面簡要介紹下Backbone的用法。

1. Backbone.Events

Events可以被新增到任何一個javascript物件中,一旦物件與Events合體,就可以自定義事件了。

 

如上,一旦使用了_.extend(obj, Backbone.Events),obj物件就獲得了自定義事件的能力。

obj.bind(event, callback) bind方法前面是事件名,後面是回撥函式。bind可以將回調函式繫結到物件上,事件觸發時便會執行回撥函式。另外,如果事件很多,可以給事件加上名稱空間,例如"poll:start", "change:selection"。

obj.unbind([event], [callback]) unbind方法就是移除事件繫結,如果event, callback都沒有,就將移除所有繫結。

obj.trigger(event,[*args]) 觸發事件。

2. Backbond.Controller

由於富Ajax的網站大多用帶#的url來識別抓取伺服器內容,因此Backbone也提供了前端的url#fragment的路由支援,並且可以把他們繫結到Action和Event中去。

注意:在使用前端路由的功能之前,一定要呼叫一次Backbone.history.start()。

我們以豆瓣說的前端程式碼為例解說下這個功能。

http://img3.douban.com/anduin/anduin-min-1307608962.js

這堆程式碼的最後一個大塊就是Controller的使用。

這一塊的大致結構如下:

 

這樣我們就很容易看出Backbone.Controller.extend(properties, [classProperties]) 的用法了。properties裡面要有一個routes的雜湊表,提供了路由和方法名的鍵值對。

所以我們看到http://shuo.douban.com/#!/comments對應著下面的comments方法。這個頁面對應著“最新回覆”模組。

我們還可以看到#fragment裡面有!這個符號,這個是給搜尋引擎識別用的,我們下次在談。

另外,還有:uid, :query, :id這些符號,如果有玩doophp, flask, bottlepy,這些符號應該也很熟悉了,這是動態的引數,uid、query、id都是這些引數的引數名,因此

http://shuo.douban.com/#!/search/users/豆瓣

就對應著"!/search/users/:query": "user_search",這個路由,繼而可以用user_search()來處理。

(特別的 "file/*path" 可以匹配#file/nested/folder/file.txt, 引數 "nested/folder/file.txt"會被傳送到相對應的Action中去。)

順便提一句,當url匹配後,會觸發一個和Action名字有關的事件,比如"!/comments": "comments",如果訪問了http://shuo.douban.com/#!/comments,就會觸發"route:comments"的事件,因此我們可以用

controller.bind("route:comments", function(){...});來處理一些額外的邏輯。

initialize方法是構造器,初始化,可以加入自定義的相關邏輯。

比如豆瓣說中

 

每當匹配了一個URL,頁面首先先去除剛才的內容,載入預設的空內容,如果登入了豆瓣說則初始化User(登入使用者),Stat(統計),Following(關注當前使用者的使用者),HomeTimeLine(時間線),Suggestion,然後用fetch獲取資料。

最後,Controller還有route、saveLocation方法,this.route("page/:number", "page", function(number){ ... });這個方法可以很快的建立一個路由,this.saveLocation("!/comments");可以不觸發hashchange時間的到達另外一個url。

3. Backbone.View

View並不操作html或者css,所有的操作留給了各種各樣JS的模板庫。

豆瓣說JS檔案倒數的十幾個塊都是與Backbone.View有關的區塊。

例如:

 

在這裡,最外層用了Backbone.View.extend(properties, [classProperties]),在initialize中一旦User類觸發了change事件就會執行render方法,繼而顯示新的檢視。

render方法中總是有個約定俗稱的寫法的。this.el是一個DOM物件,render的目的就是把內容填到this.el中。this.el會根據view提供的tagName, className, id屬性建立,如果一個都沒有,就會建立一個空的DIV。

更新完this.el後,我們還應該return this;這樣才能繼續執行下面的鏈式呼叫(如果有的話)。

豆瓣說用jquery+mustache來顯示,事實上我們還可以採用haml-js,eco等等模板,js模板在GITHUB上也是多如牛毛的。

我們也可以用$(view.el).remove()或者view.remove()很方便的清空DOM。

View層有一個委託事件的機制。直接看程式碼:

 

在這裡面有個events的鍵值對,格式為{"event selector": "callback"},其中click為事件,.btn-more是基於this.el為根的選擇器,這樣一旦約定好,接下來我們就不需要再去手動呼叫事件方法了。

4. Backbone.Model

擴充套件了Backbone.Model類的物件就會有一些特殊的方法,用來更好地管理物件。通過Backbone.Model.extend(properties, [classProperties]) 擴充套件成Backbone.Model。第二個引數可選

如下 extend中的方法是可以被子類繼承的。

 

豆瓣說中的Backbone.Model都寫得比較簡單

 

get/set用法是Model的一個特色

此外Model還有不少欄位和方法,像id, cid, excape,unset,clear,attributes, defaults等等。

內容比較繁雜,下次研究。