進入Ember.js的第三部分:深入探索

進入Ember.js的第三部分:深入探索

我希望您開始認識到 Ember.JS 是一個強大但固執(zhí)己見的框架。我們只觸及了它的表面;在我們構(gòu)建真正有用的東西之前,還有更多東西需要學習!我們將繼續(xù)使用 Ember 入門套件。在本系列的這一部分中,我們將回顧如何訪問和管理 Ember 中的數(shù)據(jù)。


使用數(shù)據(jù)

在上一篇文章中,我們使用了在控制器中定義的一組靜態(tài)顏色名稱:

App.IndexRoute = Ember.Route.extend({  setupController: function(controller) {    controller.set('content', ['red', 'yellow', 'blue']);  } }); 

這允許控制器將數(shù)據(jù)公開給索引模板。這對于演示來說很可愛,但在現(xiàn)實生活中,我們的數(shù)據(jù)源不會是硬編碼的數(shù)組。

這就是模型的用武之地。模型是應用程序使用的數(shù)據(jù)的對象表示。它可以是一個簡單的數(shù)組或從 restful json API 動態(tài)檢索的數(shù)據(jù)。通過引用模型的屬性來訪問數(shù)據(jù)本身。因此,如果我們看一下這樣的結(jié)果:

{    "login": "rey",    "id": 1,    "age": 45,    "gender": "male" } 

模型中公開的屬性是:

  • login
  • age
  • gender

通過引用模型的屬性來訪問數(shù)據(jù)本身。

正如您從上面的代碼中看到的,您可以定義一個靜態(tài)存儲,但大多數(shù)時候您將使用 Ember.Object 來定義模型。通過子類化 Ember.Object,您將能夠返回數(shù)據(jù)(例如:通過 ajax 調(diào)用)并定義您的模型。雖然您可以在控制器中顯式設置數(shù)據(jù),但始終建議您創(chuàng)建一個模型,以便遵守關注點分離和代碼組織最佳實踐。

或者,您可以使用名為 Ember Data 的姊妹框架。它是一個類似 ORM 的 API 和持久性存儲,但我需要強調(diào)的是,在撰寫本文時它正處于不斷變化的狀態(tài)。它有很大的潛力,但是此時使用 Ember.Object 更安全。 Discourse 的聯(lián)合創(chuàng)始人 Robin Ward 撰寫了一篇關于在沒有 Ember 數(shù)據(jù)的情況下使用 Ember 的精彩博客文章。它概述了他們的流程,我將為您分解。


定義模型

在下面的示例中,我將使用非官方的 Hacker News API 從新聞資源中提取基于 JSON 的數(shù)據(jù)。該數(shù)據(jù)將存儲在我的模型中,稍后由控制器用來填充模板。如果我們查看從 API 返回的數(shù)據(jù),我們就可以了解我們將使用的屬性:

{   "nextId": null,   "items": [{           "title": "Docker, the Linux container runtime: now open-source",           "url": "http://docker.io",           "id": 5445387,           "commentCount": 39,           "points": 146,           "postedAgo": "2 hours ago",           "postedBy": "shykes"       }, {           "title": "Whatu0027s Actually Wrong with Yahoou0027s Purchase of Summly",           "url": "http://hackingdistributed.com/2013/03/26/summly/",           "id": 5445159,           "commentCount": 99,           "points": 133,           "postedAgo": "2 hours ago",           "postedBy": "hoonose"       },   ],   "version": "1.0",   "cachedOnUTC": "/Date(1364333188244)/" } 

我想使用 items 屬性,其中包含所有標題和故事信息。如果您使用過 sql 數(shù)據(jù)庫,請將 items 的每個元素視為一條記錄,并將屬性名稱(即:title、url、id 等)視為字段名稱。理解布局很重要,因為這些屬性名稱將用作模型對象的屬性,這是創(chuàng)建模型的完美銜接。

Ember.Object 是所有 Ember 對象的主要基類,我們將對其進行子類化以使用其 extend() 方法創(chuàng)建我們的模型。

為此,我們將在定義 App.IndexRoute 的代碼之后立即將以下代碼添加到 js/app.js 中:

App.Item = Ember.Object.extend(); 

App.Item 用作黑客新聞數(shù)據(jù)的模型類,但它沒有檢索或操作該數(shù)據(jù)的方法。因此,我們需要定義這些:

 App.Item.reopenClass({   all: function() {       return $.getJSON("http://api.ihackernews.com/page?format=jsonp&callback=?").then(function(response) {         var items = [];          response.items.forEach( function (item) {           items.push( App.Item.create(item) );         });  	      return items;       });   } }); 

讓我們分解一下這段代碼。首先,我們使用 Ember 的 reopenClass() 方法將新方法添加到 App.Item 類中,然后向其傳遞一個包含我們所需方法的對象。對于此示例,我們只需要一個名為 all() 的方法:它返回黑客新聞首頁的所有標題。因為 jquery 是 Ember 協(xié)議的一部分,所以我們可以使用它簡單的 Ajax API。 API使用JSONP返回JSON數(shù)據(jù);所以,我可以使用 $.getJSON() 向以下位置發(fā)出請求:

$.getJSON("http://api.ihackernews.com/page?format=jsonp&callback=?") 

“回調(diào)=?”告訴 jQuery 這是一個 JSONP 請求,并且數(shù)據(jù)(一旦檢索到)將傳遞到使用 jQuery 的 promise 功能定義的匿名回調(diào)處理程序:

.then(function(response) {...}); 

我可以輕松地將 JSON 數(shù)據(jù)注入 Ember 對象。

response 參數(shù)包含 JSON 數(shù)據(jù),允許您循環(huán)記錄并使用 App.Item 的實例更新本地 items 數(shù)組。最后,當 all() 執(zhí)行時,我們返回新填充的數(shù)組。說了這么多,我總結(jié)一下:

  • 通過使用 extend() 子類化 Ember.Object 來創(chuàng)建新模型類。
  • 使用 reopenClass() 添加模型方法。
  • 進行 Ajax 調(diào)用來檢索您的數(shù)據(jù)。
  • 循環(huán)數(shù)據(jù),創(chuàng)建 Item 對象并將其推入數(shù)組中。
  • 方法執(zhí)行時返回數(shù)組。

如果您刷新index.html,您將看到?jīng)]有任何變化。這是有道理的,因為模型剛剛被定義;我們還沒有訪問過它。


公開您的數(shù)據(jù)

控制器的作用類似于代理,使您可以訪問模型的屬性并允許模板訪問它們以便動態(tài)渲染顯示。除了從關聯(lián)模型訪問屬性之外,控制器還可以存儲需要持久保存的其他應用程序?qū)傩裕鵁o需保存到服務器。

目前,我們的應用程序具有以下控制器(定義靜態(tài)數(shù)據(jù)集的控制器):

App.IndexRoute = Ember.Route.extend({   setupController: function(controller) {     controller.set('content', ['red', 'yellow', 'blue']);   } }); 

我們可以使用 model 方法(又名模型鉤子)直接將我們的模型與 App.IndexRoute 關聯(lián)起來:

App.IndexRoute = Ember.Route.extend({   model: function() {     return App.Item.all();   } }); 

請記住,如果您自己沒有顯式定義控制器,那么 Ember 會定義您的控制器,這就是本例中發(fā)生的情況。

在幕后,Ember 創(chuàng)建 IndexController 作為 Ember.ArrayController 的實例,并使用 model 方法中指定的模型。

現(xiàn)在我們只需要更新索引模板即可訪問新屬性。打開index.html,我們可以看到以下Handlebars模板代碼:

{{#each item in model}}     
  • {{item}}
  • {{/each}}

    通過一個小更改(添加 title 屬性),我們可以立即看到從 Hacker News API 返回的標題:

    {{item.title}}

    如果您現(xiàn)在刷新瀏覽器,您應該會看到類似以下內(nèi)容的內(nèi)容:

     <h3>Welcome to Ember.js</h3> 
    • Persona is distributed. Today.
    • 21 graphs that show America’s health-care prices are ludicrous
    • 10 000 concurrent real-time connections to Django
    • Docker, the Linux container runtime: now open-source
    • Let’s Say FeedBurner Shuts Down…

    如果您想顯示更多信息,只需添加更多屬性:

    {{item.title}} - {{item.postedAgo}} by {{item.postedBy}} 

    刷新即可查看您所做的更新。這就是 Handlebars 的魅力所在;它使得向用戶界面添加新數(shù)據(jù)元素變得微不足道。

    正如我之前提到的,控制器還可以用于定義需要在應用程序的整個生命周期中保留的靜態(tài)屬性。例如,我可能想保留某些靜態(tài)內(nèi)容,如下所示:

    App.IndexController = Ember.ObjectController.extend({   headerName: 'Welcome to the Hacker News App',   appVersion:  2.1 }); 

    在這里,我將 Ember.ObjectController 子類化,為我的 index 路由和模板創(chuàng)建一個新的控制器。我現(xiàn)在可以轉(zhuǎn)到 index.html 并更新我的模板以替換以下內(nèi)容:

    <h2>Welcome to Ember.js</h2> 

    與:

    <h2>{{headerName}}</h2> 

    模型是應用程序使用的數(shù)據(jù)的對象表示。

    Handlebars 將采用我的控制器中的指定屬性,并用其同名值動態(tài)替換 {{headerName}} 占位符。強調(diào)兩件事很重要:

    • 通過遵守 Ember 的命名約定,我無需進行任何接線即可將控制器與索引模板一起使用。
    • 即使我顯式創(chuàng)建了 IndexController,Ember 也足夠聰明,不會覆蓋通過路由關聯(lián)的現(xiàn)有模型。

    這是非常強大且靈活的東西!


    下一步…模板

    在 Ember 中處理數(shù)據(jù)并不困難。實際上,最困難的部分是使用網(wǎng)絡上大量的各種 API。

    事實上,我可以輕松地將 JSON 數(shù)據(jù)輸入到 Ember 對象中,這使得管理變得更加容易 — 盡管我從來都不是客戶端大型數(shù)據(jù)集的忠實粉絲,尤其是當表示為對象時.

    這是我必須做更多測試的事情,我希望 Ember Data 能讓這一切變得微不足道。

    話雖如此,我在本文中簡要介紹了模板。它們非常重要……以至于我想在自己的文章中討論這個主題。因此,在下一篇文章中,我們將介紹如何利用 Handelbars 構(gòu)建用戶界面,并深入了解模板框架提供的各種指令。

    ? 版權聲明
    THE END
    喜歡就支持一下吧
    點贊15 分享