與 Web 開發同行不同,JavaScript 從來沒有真正以框架的方式提供結構。值得慶幸的是,近年來,這種情況開始發生變化。
今天,我想向您介紹 Backbone.JS,這是一個可愛的小庫,它使創建復雜、交互式和數據驅動的應用程序的過程變得更加容易。它提供了一種干凈的方法來將數據與演示文稿分離。
Backbone.JS 概述
Backbone 由構建 coffeescript 的 JS 忍者 Jeremy Ashkenas 創建,是一個超輕量級庫,可讓您創建易于維護的前端。它與后端無關,并且可以與您已經使用的任何現代 JavaScript 庫配合良好。
Backbone 是一個內聚對象的集合,重量4kb以下,它為您的代碼提供結構,基本上可以幫助您在瀏覽器中構建適當的 mvc 應用程序。官方網站是這樣描述其目的的:
Backbone 通過提供具有鍵值綁定和自定義事件的模型、具有豐富的可枚舉函數 API 的集合、具有聲明性事件處理的視圖,為 JavaScript 密集型應用程序提供結構,并將其全部連接到您現有的應用程序restful json 接口。
讓我們面對現實:上面的內容有點難以解析和理解。因此,讓我們在 Jeremy 的幫助下繼續解構這些行話。
鍵值綁定和自定義事件
當模型的內容或狀態發生更改時,已訂閱該模型的其他對象會收到通知,以便它們可以進行相應的處理。在這里,視圖監聽模型中的變化,并相應地更新自己,而不是模型必須手動處理視圖。
豐富的可枚舉函數API
Backbone 附帶了許多非常有用的函數來處理和使用您的數據。與其他實現不同,JavaScript 中的數組是相當中性的,當您必須處理數據時,這確實是一個阻礙問題。
具有聲明性事件處理的視圖
你編寫意大利面條式綁定調用的日子已經結束了。您可以通過編程方式聲明哪個回調需要與特定元素關聯。
RESTful JSON 接口
盡管當您想要與服務器通信時默認方法是使用標準 ajax 調用,但您可以輕松地將其切換為您需要的任何內容。許多適配器如雨后春筍般涌現,涵蓋了大多數最受歡迎的適配器,包括 Websockets 和本地存儲。
將其分解為更簡單的術語:
Backbone 提供了一種干凈的方法來將數據與演示文稿分離。處理數據的模型只關心與服務器同步,而視圖的主要職責是監聽訂閱模型的更改并呈現 html。
快速常見問題解答
我猜您現在可能有點困惑,所以讓我們澄清一些事情:
它會取代 jquery 嗎?
沒有。它們的范圍非常互補,功能上幾乎沒有重疊。 Backbone 處理所有更高級別的抽象,而 jQuery(或類似的庫)則處理 dom、規范化事件等。
它們的范圍和用例非常不同,因為你知道其中一個并不意味著你不應該學習另一個。作為一名 JavaScript 開發人員,您應該知道如何有效地使用兩者。
我為什么要使用這個?
因為通常情況下,前端代碼會變成一堆熱氣騰騰、臟兮兮的嵌套回調、DOM 操作、用于演示的 HTML 以及其他不可言喻的行為。
Backbone 提供了一種非常干凈和優雅的方式來管理這種混亂。
我應該在哪里使用它?
Backbone 非常適合創建前端重型、數據驅動的應用程序。想想 GMail 界面、新 Twitter 或過去幾年的任何其他啟示。它使創建復雜的應用程序變得更加容易。
雖然您可以將其硬塞到更主流的網頁頁面,但這實際上是一個專為網絡應用程序量身定制的庫。
它與卡布奇諾或 Sproutcore 類似嗎?
是和否。
是的,因為與上面提到的框架一樣,這主要用于為 Web 應用程序創建復雜的前端。
它的不同之處在于 Backbone 非常精簡,并且沒有附帶其他小部件。
Backbone 的重量非常輕,不到 4kb。
還有一個事實是,Cappuccino 強制您使用 Objective-J 編寫代碼,而 Sproutcore 的視圖必須在 JS 中以編程方式聲明。雖然這些方法都沒有錯,但使用 Backbone,普通的 JavaScript 可以通過常用的 HTML 和 css 來完成工作,從而實現更溫和的學習曲線。
我仍然可以在頁面上使用其他庫,對吧?
絕對是的。不僅是典型的 DOM 訪問、AJAX 包裝類型,還有其余的模板和腳本加載類型。它的耦合非常非常松散,這意味著您可以將幾乎所有工具與 Backbone 結合使用。
它會帶來世界和平嗎?
不,抱歉。但這里有一些東西可以讓你振作起來。
好的,現在拋開這個問題,讓我們開始吧!
了解 Backbone 的 Backbone
Backbone 中的 MVC 最初代表模型、視圖和集合,因為框架中沒有控制器。此后情況發生了變化。
Backbone 的核心由四個主要類組成:
- 型號
- 集合
- View
- 控制器
由于我們時間有點緊張,所以我們今天只看一下核心課程。我們將使用一個超級簡單的應用程序進行后續操作,以演示此處教授的概念,因為將所有內容都放在一篇文章中并期望讀者解析所有內容會太多。
在接下來的幾周內請保持警惕!
型號
模型在不同的 MVC 實現中可能有不同的含義。在 Backbone 中,模型代表一個單一實體——數據庫中的記錄(如果您愿意的話)。但這里沒有硬性規定。來自 Backbone 網站:
模型是任何 JavaScript 應用程序的核心,包含交互式數據以及圍繞它的大部分邏輯:轉換、驗證、計算屬性和訪問控制。
該模型只是為您提供了一種在數據集上讀取和寫入任意屬性或屬性的方法。考慮到這一點,下面的單行代碼是完全可用的:
var Game = Backbone.Model.extend({});
讓我們在此基礎上進一步發展。
var Game = Backbone.Model.extend({ initialize: function(){ alert("Oh hey! "); }, defaults: { name: 'Default title', releaseDate: 2011, } });
initialize 將在實例化對象時被觸發。在這里,我只是提醒大家注意一些愚蠢的行為——在您的應用程序中,您可能應該引導數據或執行其他內務處理。我還定義了一堆默認值,以防沒有數據被傳遞。
我們來看看如何讀寫屬性。但首先,讓我們創建一個新實例。
// Create a new game var portal = new Game({ name: "Portal 2", releaseDate: 2011}); // release will hold the releaseDate value -- 2011 here var release = portal.get('releaseDate'); // Changes the name Attribute portal.set({ name: "Portal 2 by Valve"});
如果您注意到 get/set 變異器,請吃一塊 Cookie!無法通過典型的 object.attribute 格式讀取模型的屬性。您必須執行 getter/setter,因為錯誤更改數據的可能性較低。
此時,所有更改僅保留在內存中。讓我們通過與服務器對話來使這些更改永久生效。
portal.save();
就是這樣。你期待更多嗎?上面的一行代碼現在將向您的服務器發送一個請求。請記住,請求的類型會智能地改變。由于這是一個新對象,因此將使用 POST。否則,使用 PUT。
Backbone 模型默認提供更多功能,但這絕對可以幫助您入門。點擊文檔以獲取更多信息。
集合
Backbone 中的集合本質上只是模型的集合。與之前的數據庫類比一樣,集合是查詢的結果,其中結果由許多記錄[模型]組成。您可以像這樣定義一個集合:
var GamesCollection = Backbone.Collection.extend({ model : Game, } });
首先要注意的是,我們正在定義這是哪個模型的集合。擴展我們之前的示例,我將這個集合作為游戲集合。
現在您可以繼續隨心所欲地使用您的數據。例如,讓我們擴展該集合以添加僅返回特定游戲的方法。
var GamesCollection = Backbone.Collection.extend({ model : Game, old : function() { return this.filter(function(game) { return game.get('releaseDate') <p>這很容易,不是嗎?我們僅檢查游戲是否在 2009 年之前發布,如果是,則退回該游戲。</p> <p>您還可以直接操作集合的內容,如下所示:</p> <pre class="brush:javascript;toolbal:false;"> var games = new GamesCollection games.get(0);
上面的代碼片段實例化了一個新的集合,然后檢索 ID 為 0 的模型。您可以通過引用 at 方法的索引來查找特定位置的元素,如下所示: 游戲.at(0);
最后,您可以像這樣動態填充您的集合:
var GamesCollection = Backbone.Collection.extend({ model : Game, url: '/games' } }); var games = new GamesCollection games.fetch();
我們只是讓 Backbone 通過 url 屬性從何處獲取數據。完成后,我們只需創建一個新對象并調用 fetch 方法,該方法會觸發對服務器的異步調用并使用結果填充集合。
這應該涵蓋 Backbone 集合的基礎知識。正如我提到的,這里有大量的好東西,其中 Backbone 別名了 Underscore 庫中的許多漂亮的實用程序。快速閱讀官方文檔應該可以幫助您入門。
查看
乍一看,Backbone 中的視圖可能會有些混亂。對于 MVC 純粹主義者來說,它們類似于控制器而不是視圖本身。
視圖從根本上處理兩項職責:
- 監聽 DOM 和模型/集合拋出的事件。
- 向用戶展示應用的狀態和數據模型。
讓我們繼續創建一個非常簡單的視圖。
GameView= Backbone.View.extend({ tagName : "div", className: "game", render : function() { // code for rendering the HTML for the view } });
如果您到目前為止一直在學習本教程,那么相當簡單。我只是通過 tagName 屬性指定應該使用哪個 HTML 元素來包裝視圖,并通過 className 指定它的 ID。
讓我們繼續進行渲染部分。
render : function() { this.el.innerHTML = this.model.get('name'); //Or the jQuery way $(this.el).html(this.model.get('name')); }
el 指的是視圖引用的 DOM 元素。我們只是通過元素的 innerHTML 屬性訪問游戲的名稱。簡而言之,div 元素現在包含我們游戲的名稱。顯然,如果您以前使用過該庫,則 jQuery 方式會更簡單。
對于更復雜的布局,在 JavaScript 中處理 HTML 不僅乏味而且魯莽。在這些情況下,模板是可行的方法。
Backbone 附帶了由 Underscore.JS 提供的最小模板解決方案,但我們非常歡迎您使用任何可用的優秀模板解決方案。
最后我們看一下視圖是如何監聽事件的。首先是 DOM 事件。
events: { 'click .name': 'handleClick' }, handleClick: function(){ alert('In the name of science... you monster'); // Other actions as necessary }
如果您以前處理過事件,那么應該很簡單。我們基本上是通過事件對象定義和連接事件。正如您在上面看到的,第一部分指的是事件,下一部分指定觸發元素,最后一部分指應觸發的函數。
現在綁定到模型和集合。我將在這里介紹模型的綁定。
GameView= Backbone.View.extend({ initialize: function (args) { _.bindAll(this, 'changeName'); this.model.bind('change:name', this.changeName); }, });
首先要注意的是我們如何將綁定代碼放置在初始化函數中。當然,最好從一開始就這樣做。
bindAll 是 Underscore 提供的一個實用程序,用于保存函數的 this 值。這特別有用,因為我們傳遞了一堆函數,并且指定為回調的函數已刪除該值。
現在,只要模型的 name 屬性發生更改,就會調用 changeName 函數。您還可以使用添加和刪除動詞來輪詢更改。
偵聽集合中的更改就像將處理程序綁定到回調時將模型替換為集合一樣簡單。
控制器
Backbone 中的控制器本質上允許您使用 hashbang 創建可添加書簽的有狀態應用程序。
var Hashbangs = Backbone.Controller.extend({ routes: { "!/": "root", "!/games": "games", }, root: function() { // Prep the home page and render stuff }, games: function() { // Re-render views to show a collection of books }, });
這對于傳統服務器端 MVC 框架中的路由非常熟悉。例如,!/games 將映射到 games 函數,而瀏覽器本身中的 URL 將是 domain/#!/games。
通過智能使用 hashbang,您可以創建大量基于 JS 且可添加書簽的應用程序。
如果您擔心破壞后退按鈕,Backbone 也能滿足您的需求。
// Init the controller like so var ApplicationController = new Controller; Backbone.history.start();
通過上面的代碼片段,Backbone 可以監控您的 hashbang,并結合您之前指定的路線,使您的應用程序可添加書簽。
我從 Backbone 學到了什么
總的來說,以下是我從創建應用程序的 Backbone 方式中學到的一些經驗教訓:
- 前端確實需要 MVC。傳統方法給我們留下的代碼過于耦合、混亂且難以維護。
- 在 DOM 中存儲數據和狀態是一個壞主意。在創建需要使用相同數據更新應用的不同部分的應用后,這開始變得更有意義。
- 胖模型和瘦控制器是正確的選擇。當業務邏輯由模型處理時,工作流程就會得到簡化。
- 模板是絕對必要的。將 HTML 放入 JavaScript 中會給您帶來不好的業力。
可以說 Backbone 引起了前端構建方式的范式轉變,至少對我來說是這樣。鑒于今天文章的范圍非常廣泛,我確信您有很多問題。點擊下面的評論部分來插話。非常感謝您的閱讀,并期待將來有更多的 Backbone 教程!