深刻理解Ember-Data特性(下)

寫在前面

         最近比較忙,換了新工做還要學習不少全新的技術棧,並給本身找了不少藉口來不去堅持寫博客。經常具備諷刺意味的是,更多剩下的時間並無利用而更多的是白白浪費,也許這就是青春吧,揮霍吧,這不是我想要的,既然這樣,我還要繼續寫下去,堅持把博客作好,爭取進前100博客,在此謹記。html

                                                                                                         2015年5月7日深夜,於電腦旁。前端

文章索引

JS前端框架之Ember.js系列git

 

2、使用Ember-Data

  爲了更好的使用Ember-Data,你就須要使用Store,Store你能夠認爲是一個內存緩存,Ember-Data使用它去恢復和保存數據模型。事實上,Store還負責從服務端獲取數據,經過已綁定的Adapter。github

  還能夠自定義Adapter:json

  或者自定義serializer:api

  這裏僅僅是指出自定義場景,接下來會詳細分析。數組

Model中獲取數據

  下面列舉兩種簡單的獲取數據方式:緩存

  1. Store.find(‘mainMenu’); 這種方式是試圖獲取mainMenu類型的全部數據。
  2. Store.find(‘mainMenu’,’JSFlotJAgent’);這種方式是試圖獲取類型爲mainMenu, id爲「JSFlotJAgent」類型的數據。

 

  更多例子請參考:http://emberjs.com/api/data/classes/DS.Store.html前端框架

標識模型關係

         以上模型中的mainMenu以及Children類型同爲mainMenu,造成一個「無限極」樹的概念,循環嵌套節點對象,下圖展現了模型中mainMenu和Chart的關係圖:服務器

注:上圖中的OneToOne、OneToMany等是有歧義,做者的這幅圖應該改成OneToNone、ManyToNone。

  這裏mainMenu有一個parent節點標識上一層引用關係,一個children節點來表示孩子節點的集合,最後還有一個一對一的chart來表示圖表數據。能夠將chart理解爲一個節點中的主要內容,parent和children則表示當前節點所在位置、關聯關係,有些相似於兩個指針分別指向父節點和孩子節點。

  接下來一節咱們詳細分析Ember-Data中的模型關係。

3、Ember-Data模型關聯關係

         Ember-Data支持多種數據關係類型,這些關係類型用來指望從數據端返回的數據類型結構,接下來咱們來詳細分析這些API的做用。

 

理解Ember-Data關係模型

         Ember-Data定義了5中關係模型,其中三種是真正的類型,另外兩種能夠理解爲特殊例子。

注:圖中第二行的OneToNone替換成OneToOne,做者這裏多是筆誤。

  其中,上一節咱們講過,Ember-Data中有不少約定,例如定義的屬性要Camel風格(如modelA),列表數組屬性結尾要用s(如modelAs),全部id要惟一性,這樣便於讀取從服務端傳來的JSON Hash對象。

理解Ember-Data邊緣(sideloaded)加載

  邊緣式加載的是經過增長數據層級來分步加載(能夠理解爲先加載第一層次的數據集合,而後按需加載子一級的數據集合)。

  咱們先來看下Model的定義:

  這是一個典型的文章及評論的結構,即一個文章包含有多條評論,一條評論屬於一篇文章。

  下面來讓咱們看看邊緣式加載是如何工做的:

  當請求類型全部數據時,Ember-Data發現倉庫中沒有此類數據,則向服務器發起請求,而服務器僅僅返回文章內容及評論id(能夠理解爲僅僅返回評論的預覽,而非一條評論的所有信息),而後當再次請求評論詳情時,服務端返回評論的真實信息。

  你能夠在第一次請求數據時,讓服務端返回全部數據:(而不是等待評論請求時再返回)

  注:這樣的場景下,若是用戶沒有查看評論,則評論永遠也沒有被顯示出來,也就是說數據可能毫無心義的加載了。

  固然這還要取決於你的數據場景,可能這樣模式並不適合你,這樣作會產生更多的HTTP請求,但同時又減少了「可用」數據的返回量,如何取捨還需仔細分析,固然你也能夠自定義如何返回數據。

4、定製Adapter和Serializer

  這裏Ember提供了三種基本的重寫Adapter的場景:

  1. 服務端API傳來的數據對數據類型沒有通用的標準。
  2. 服務端API傳來的數據不一樣於你定義的數據類型。
  3. 重寫Adapter並保留Serializer,來保證服務端傳來的Json數據頂級結構中的類型與你定義的類型不一樣,而子類型相同。

 

定製Adapter

  下面來讓咱們看下這種場景:

  在咱們上一節的數據類型中,mainMenu包含一個一對一的Chart類型,如今的需求是但願能夠設置Chart的Timespan來部分獲取Chart數據,若是沒有設置則默認爲10minutes。

  首先,從DS.RESTAdapter中擴展一個類型,而且要遵循Adapter的命名規範(XXXXAdapter這種模式必須遵循)。

  而後,能夠重寫以下的方法:

  對於咱們目前的需求來講,咱們僅僅須要重寫find()方法便可,方法中將進行一個HTTP請求。

  其中,重要的是用Timespan重組http請求,已達到咱們的目的。

  更多請參考:http://guides.emberjs.com/v1.11.0/models/customizing-adapters/

定製Serializer

  相對於RESTSerializer而言,咱們給出以下的非標準數據模型:

  在這個返回類型中,user_name、account_name、user_role是非標準的數據相對RESTSerializer來講。並且最頂層的屬性名稱user_model也不符合。

  咱們能夠重寫Adapter中的方法以達到咱們的目的:

         這裏咱們須要重寫normalize方法爲了解決user_name、account_name、user_role非標準化問題,重寫typeForRoot方法解決user_model問題。

定製URL

         你能夠定製Adapter的ULR訪問類型以及轉換定義,下面是一個很好的例子:

  最終將訪問以下網址:http://api.myapp.com/json/v1/mainMenus

FAQ

  1. 使用Store存儲數據的優點是否能結合Filter?

Store能自動cache數據並保持數據同一性,經過id屬性。而且容許用戶使用Filter來過濾不須要的數據。

  1. Ember-Data如何通知新數據已經到達?

當你使用store.find()時,數據會自動更新RecordArray,任何計算屬性或者監聽在RecordArray上都將得到通知。若是你不須要請求而且要加載數據的話,可使用Store.push或者pushPayload 來向Store中推送數據,這樣Store也會得到監聽事件的觸發。例如SSE或WebSocket場景。

引用

  Ember-Data更新日誌:https://github.com/emberjs/data/blob/master/TRANSITION.md

  參考書目:《Ember.js In Action》 

相關文章
相關標籤/搜索