有很多可用的 JavaScript 庫,其中大多數都非常擅長提供典型網站所需的傳統的以 DOM 為中心的交互。但是,當需要為單頁應用程序構建可管理的代碼庫時,就需要一整套新框架來解決問題。
老話說得好:“用最好的工具完成任務”。
并不是說像 jQuery 這樣的傳統庫不能幫助您構建類似桌面的體驗,它只是不是它的用例,并且缺少數據綁定、事件路由和狀態管理等功能。當然,您可能可以拼湊一堆插件來實現其中一些功能,但在我看來,從專門從頭開始構建的框架來解決這些特定問題更有意義。老話說得好:“用最好的工具完成任務。”
我最近接受了 Ember.js 團隊的采訪;我的動機是想要了解我所說的“新熱點”:Ember.js。
Ember 符合我上面描述的要求,并且以一種讓人想起 jQuery 如何讓開發人員快速啟動和運行的方式。該團隊特意采取措施,利用多年從構建大型應用程序中獲得的專業知識和知識,抽象化了設計和構建基于模型/視圖/控制器的應用程序所固有的許多復雜性。
我想做的是通過一個由多部分組成的文章系列幫助您加快使用 Ember.js 的速度,該系列文章將逐步向您介紹該框架的概念。我們將從通常的介紹開始(恰好是這篇文章),然后逐漸構建一個完整的應用程序。最重要的是,這也將幫助我強化我已經學到的概念,也許還能學到一些新技術!我會盡力讓 Ember.js 團隊審查此材料的準確性,甚至可能為其貢獻一些有價值的內容。
在我們繼續之前,請注意:Ember.js 為您帶來了很多魔力。有時您會看著代碼并說“啊?它是怎么做到的?”我已經去過那里了,我會盡力提煉一些東西,但我不會深入研究 Ember 框架代碼的內部。相反,我將討論如何利用其工具和 API 來構建您的應用程序。
所以讓我們開始吧。
核心概念
Ember.js 不是構建傳統網站的框架。
首先要記住的是,Ember.js 不是用于構建傳統網站的框架。像 jQuery 和 MooTools 這樣的庫非常適合這一點。如果您正在考慮 Ember.js,那么我們的假設是您正在尋求構建類似桌面的體驗 – 尤其是可擴展的體驗。事實上,該框架的口號是“一個用于開發雄心勃勃的 Web 應用程序的框架”,這告訴您它顯然不是您爸爸的 JavaScript 庫。
我之前提到過,Ember 利用 MVC 模式來促進正確的代碼管理和組織。如果您從未進行過基于 MVC 的開發,那么您絕對應該閱讀它。 Nettuts+ 有一篇關于該主題的精彩文章。對于那些熟悉這些概念的人來說,您應該有賓至如歸的感覺。我一直聽到的一件事是,從 Backbone 遷移到 Ember.js 實際上很容易,因為 Ember 為您做了很多繁重的工作,同時仍然保持那些開發人員習慣的代碼組織模式。 p>
Ember 還依賴于客戶端模板……很多。它使用 Handlebars 模板庫,該庫提供允許您創建基于 HTML 的動態模板的表達式。 Ember 開發人員可以將數據綁定到這些可嵌入表達式,并動態更改其應用程序的顯示。例如,我可以創建一個模板,該模板可以接收一組人員并將其顯示在無序列表中:
- {{#each people}}
- Hello, {{name}}!
{{/each}}
注意“#each”表達式用作循環指令,枚舉“people”數組的每個元素并將“{{name}}”表達式替換為實際值。需要注意的是,雙括號是 Handlebars 用來識別表達式的標記。這是一個小示例,稍后我們將深入了解更多細節。
Handlebars 是一個非常強大的客戶端模板引擎,我建議不僅查看 Ember 指南,還查看 Handlebars 網站本身,以充分掌握可用的選項。您將會經常使用它。
設置 Ember
Ember.js 依賴于其他庫,因此您需要獲取 jQuery 和 Handlebars 的副本。但是,等等,我不是說過 jQuery 和 Ember 在不同的空間發揮作用嗎?嗯,是的,我做到了,但事情是這樣的:Ember 團隊致力于不重新發明輪子。他們選擇 jQuery 來做它最擅長的事情:使用 DOM。這是一件好事,因為 jQuery 在這方面確實很擅長。這也是他們選擇 Handlebars 的原因,這是一個出色的模板庫,恰好由 Ember 核心團隊成員 Yehuda Katz 編寫。
獲取所需文件的最簡單方法是訪問 Ember.js Github 存儲庫并下載入門工具包。這是供您開始使用的樣板。在撰寫本文時,它包含:
- 人類 1.0 RC1
- 處理欄 1.0 RC3
- jQuery 1.9.1
還有一個基本的 html 模板,其編碼包含所有關聯的庫(jQuery、Ember 等),以及 Handlebars 模板和“app.js”的示例,其中包含用于啟動基本的 Ember 應用程序。
<script src="js/libs/jquery-1.9.1.js"></script><script src="js/libs/handlebars-1.0.0-rc.3.js"></script><script src="js/libs/ember-1.0.0-rc.1.js"></script><script src="js/app.js"></script>
請注意,app.js 不是框架的一部分。這是一個普通的 ole JavaScript 文件;您可以將其命名為任何您想要的名稱。而且,雖然我們將在本教程系列中使用它,但以后您可能最終會將 JavaScript 拆分為多個文件,就像處理任何其他網站或應用程序一樣。此外,Ember 并不期望您的框架文件有特定的目錄結構。
當您查看入門工具包代碼時,它可能看起來像典型的網站代碼。從某些方面來說,你是對的!不過,一旦我們開始組織事情,您就會看到構建 Ember 應用程序有何不同。
余燼之地的布局
在開始編寫代碼之前,了解 Ember.js 的工作原理以及了解構成 Ember 應用程序的移動部件非常重要。讓我們看一下這些部分以及它們之間的關系。
模板
模板是定義用戶界面的關鍵部分。正如我之前提到的,Handlebars 是 Ember 中使用的客戶端庫,在為應用程序創建 UI 時廣泛使用該庫提供的表達式。這是一個簡單的例子:
<script type="text/x-handlebars"> <h2><strong>{{firstName}} {{lastName}} </script>
請注意,表達式會混合到 HTML 標記中,并通過 Ember 動態更改頁面上顯示的內容。在這種情況下,{{firstName}} 和 {{lastName}} 占位符將被從應用檢索的數據替換。
Handlebars 通過靈活的 API 提供強大的功能。了解它提供的功能對您來說非常重要。
路由
應用程序的路由器有助于管理應用程序的狀態。
應用程序的路由器有助于管理應用程序的狀態以及用戶導航應用程序時所需的資源。這可能包括從模型請求數據、將控制器連接到視圖或顯示模板等任務。
您可以通過為應用程序中的特定位置創建一條路線來實現此目的。路由指定應用程序的各個部分以及與其關聯的 URL。 URL 是 Ember 用于了解需要向用戶呈現哪種應用程序狀態的關鍵標識符。
App.Router.map( function() { this.route( 'about' ); // Takes us to "/about" });
路由的行為(例如:從模型請求數據)通過 Ember 路由對象的實例進行管理,并在用戶導航到特定 URL 時觸發。一個示例是從模型請求數據,如下所示:
App.EmployeesRoute = Ember.Route.extend({ model: function() { return App.Employee.find(); } });
在本例中,當用戶導航到應用程序的“/employees”部分時,路由會向模型請求所有員工的列表。
模型
數據的對象表示。
模型是應用程序將使用的數據的對象表示。它可以是一個簡單的數組或通過 Ajax 請求從 RESTful JSON API 動態檢索的數據。 Ember 數據庫提供了用于在應用程序中加載、映射和更新數據到模型的 API。
控制器
控制器通常用于存儲和表示模型數據和屬性。它們就像代理一樣,使您可以訪問模型的屬性并允許模板訪問它們以動態渲染顯示。這就是模板始終連接到控制器的原因。
要記住的主要事情是,當模型檢索數據時,您將使用控制器以編程方式將該數據公開給應用程序的不同部分。雖然模型和控制器看起來緊密耦合,但事實上,模型本身并不知道稍后將使用它們的控制器。
您還可以存儲需要保留但不需要保存到服務器的其他應用程序屬性。
觀看次數
Ember.js 中的視圖旨在管理圍繞用戶交互的事件,并將其轉換為在應用程序中有意義的事件。因此,如果用戶單擊按鈕來刪除員工,則視圖負責解釋本機瀏覽器單擊事件并在應用程序當前狀態的上下文中對其進行適當處理。
命名約定
Ember.js 幫助最大程度地減少所需代碼量并在幕后為您處理事務的方法之一是通過命名約定。定義和命名路由(和資源)的方式會影響控制器、模型、視圖和模板的命名。例如,如果我創建一條名為“employees”的路線:
App.Router.map( function() { this.resource( 'employees' ); });
然后我會命名我的組件,如下所示:
- 路由對象: App.EmployeesRoute
- 控制器: App.EmployeesController
- 模型: App.Employee
- 視圖: App.EmployeesView
- 模板: 員工
使用此命名約定有雙重目的。首先,它為您提供了類似組件之間的語義關系。其次,Ember 可以自動創建可能不存在的必要對象(例如:路由對象或控制器)并將它們連接起來以便在您的應用程序中使用。這就是我前面提到的“魔力”。事實上,當您實例化 Application 對象時,這就是 Ember 在全局應用程序級別所做的具體操作:
var App = Ember.Application.create();
該單行創建對應用程序的路由器、控制器、視圖和模板的默認引用。
- 路由對象: App.ApplicationRoute
- 控制器: App.ApplicationController
- 視圖: App.ApplicationView
- 模板:應用程序
回到我上面創建的“employees”路由,當用戶導航到應用程序中的“/employees”時,Ember 將查找以下對象:
- App.EmployeesRoute
- App.EmployeesController
- 員工模板
如果沒有找到它們,它將創建每個實例的實例,但不會渲染任何內容,因為您尚未指定從中派生數據的模型或用于顯示數據的模板。這就是命名約定如此重要的原因。它讓 Ember 知道如何處理與特定路線相關的任務,而無需您手動進行連接。
請注意,在第一個示例中,我使用單數名稱“Employee”來定義模型。這是故意的。 “員工”這個名稱的本質決定了我可能會與 0 到多名員工一起工作,因此構建一個可以靈活返回一名員工或所有員工的模型非常重要。該模型的單一命名約定不是 Ember 的要求,因為模型本身不知道稍后將使用它們的控制器。因此,您可以靈活地命名它們,但為了保持一致性,堅持此約定將使您的代碼管理變得更加容易。
此外,我選擇使用 resource() 方法來定義我的路由,因為在這種情況下,我很可能使用嵌套路由來管理特定員工信息的詳細信息頁面。我們將在本系列后面討論嵌套。
關鍵要點是,通過使用一致的命名方案,Ember 可以輕松管理將這些組件綁定在一起的掛鉤,而無需通過大量代碼顯式定義關系。
項目網站上提供了 Ember 命名約定的完整詳細信息,必讀。
下一步:構建應用程序
在本系列的下一部分中,我們將深入研究代碼來為我們的應用程序創建基礎。
我們已經回顧了 Ember 的核心概念,并討論了該框架的關鍵高級方面。在本系列的下一部分中,我們將深入研究代碼來為我們的應用程序創建基礎。在此期間,我想再次建議您開始查看 Handlebars 的文檔,以了解表達式語法。另外,如果您真的迫不及待地想要進入 Ember,請繼續關注 Tuts+ Premium,它將很快提供完整的課程,引導您構建基于 Ember 的應用程序!
正如我在本文開頭指出的,Ember.js 核心團隊領導 Yehuda Katz 和 Tom Dale 審查了此內容的準確性,并豎起大拇指。 Ember 團隊已獲批準!一會兒見!