摘要:由于能力有限本示例不會完全自定義適配器和序列化器,示例仍然是使用官方推薦方式,重寫或者擴展以實現(xiàn)自定適配器和序列化器。在序列化器中調(diào)用響應(yīng)請求的方法格式化返回的數(shù)據(jù)。上述就是的一個簡單實用示例。
文章來源:http://xcoding.tech/tags/Emberjs
歡迎訪問源網(wǎng)站Ember Teach,Ember Teach致力于為您提供最權(quán)威、最前沿的Ember技術(shù)教程。。
adapter與serializer相對來說是比較高級的內(nèi)容。但是也是非常常用的一個組件,最常用到這兩個組件的就是Ember Data。Ember Data已經(jīng)實現(xiàn)了這兩個組件,并且提供了非常豐富的API,如果要自定義適配器和序列化器一般都是擴展或者是重寫JSONAPIAdapter,這也是官方建議的方式,JSONAPIAdapter是遵循json api規(guī)范的適配器,主要表現(xiàn)在數(shù)據(jù)的交換格式必須遵循JSONAPI規(guī)范。當然如果你想完全重新實現(xiàn)一套自定義的適配器和序列化器也是可以的,官方建議是基于Adapter做擴展。由于能力有限本示例不會完全自定義適配器和序列化器,示例仍然是使用官方推薦方式,重寫或者擴展JSONAPIAdapter以實現(xiàn)自定適配器和序列化器。
那么我們?yōu)楹涡枰远x適配器呢?很明顯的一個原因就是Ember.js并沒有提供數(shù)據(jù)存儲方案,Ember目前更多的只是一個前端的MVC框架,數(shù)據(jù)的存儲服務(wù)還是要開發(fā)者提供,目前比較流行的做法是使用谷歌的Firebase,F(xiàn)irebase是一個實時更新數(shù)據(jù)的后端服務(wù),國內(nèi)也有類似的跟隨者(野狗)但是目前野狗還沒有Ember的適配器,相反Firebase提供了完備的Ember適配器,使用起來非常方便,而且還提供了免費的服務(wù)??梢哉f除了網(wǎng)速比較慢之外是非常適合做Ember的數(shù)據(jù)服務(wù)的。但是比較遺憾的是我們在天朝內(nèi),你懂滴,谷歌的東西在我們這個國度要使用還是不怎么順暢的。那么既然不能使用現(xiàn)有的輪子那么我們只能使用自己的后端數(shù)據(jù)服務(wù)了,此時就必須要自定義適配器了(我們能直接使用Firebase的原因就是Firebase提供完美的適配器,不需要開發(fā)者去開發(fā),直接使用即可)。
Ember所推崇是“約定由于配置”,所有Ember默認了很多規(guī)則,自然適配器和序列化器也不例外,所以本例子程序會包括兩個方面的東西,一個是Ember項目本身;另一個是為Ember項目提供服務(wù)器的后端數(shù)據(jù)庫以及數(shù)據(jù)庫處理程序。
主要軟件說明MongoDB
NodeJS
Mongoose
json api服務(wù)端
Ember CLI
上述軟件的安裝與配置請自行根據(jù)各自官網(wǎng)文檔介紹安裝配置,如果你想使用其他數(shù)據(jù)庫也是可以的,但是處理起來可能沒有MongoDB那么方便,如果你看過jsonapi規(guī)范就知道,jsonapi相對于普通的json數(shù)據(jù)還是有挺大差別的,如果是使用其他數(shù)據(jù)庫(比如MySQL)處理起來可能稍微麻煩一些,另外一個很重要的原因就是json API插件大部分都是node版的,說了這么多其實就是想把服務(wù)器返回的數(shù)據(jù)格式格式化為jsonapi規(guī)范,否則其他格式的數(shù)據(jù)JSONAPIAdapter適配器是無法識別的,會報錯。
再啰嗦幾句:一個APP之所以能與后端服務(wù)良好交互,其他交互的數(shù)據(jù)格式都是比較固定的,Ember也不例外,因為Ember Data所接受的數(shù)據(jù)格式是jsonapi,所以我們的后端服務(wù)返回的數(shù)據(jù)格式必須符合jsonapi規(guī)范,當然如果你不是使用Ember Data,你使用的是其他的數(shù)據(jù)持久化庫也是可以的,那么相對的你的的后端數(shù)據(jù)服務(wù)返回的數(shù)據(jù)格式就要跟你的持久化庫相匹配就可以了,如果你想使用其他的持久化庫你可以參考jsonapi client libraries,上面提供了各個語言的持久化庫。
搭建項目言歸正傳,下面結(jié)合一個小例子講解如何去自定義適配器去連接到自己的數(shù)據(jù)庫,并把數(shù)據(jù)持久化到數(shù)據(jù)庫中。
使用Ember CLI創(chuàng)建一個普通的Ember項目,命令如下:
ember new ember-adapter-serializer cd ember-adapter-serializer ember s
啟動項目后預(yù)覽http://localhost:4200,可以看到Ember常規(guī)的歡迎信息,說明項目創(chuàng)建成功。
創(chuàng)建路由、模型、模板仍然是使用Ember CLI命令創(chuàng)建演示示例所需的路由、模型、模板文件,本示例會構(gòu)建一個簡單的博客項目,目的主要是為了使項目盡量包含模型的一對一、一對多、多對多關(guān)系,這些關(guān)系是一個適配器比較關(guān)鍵的東西(簡單理解,其實適配器就像MVC項目中的DAO層,專門做數(shù)據(jù)處理的)。
創(chuàng)建命令如下:
ember g route users ember g model user ember g route users/list ember g route users/new ember g route users/edit ember g route posts ember g model post ember g route tags ember g model tag ember g route comments ember g model comment
后續(xù)使用到其他的文件再創(chuàng)建。
模型處理模型的處理主要是設(shè)置模型的屬性以及模型之間的關(guān)系,在本例子中定義了3個模型:user、post、tag、comment。他們的關(guān)系如下:
user與post是一對多的關(guān)系
user與comment是一對多的關(guān)系
post與comment也是一對多的關(guān)系
post與tag是多對多關(guān)系
各個模型代碼如下:
user// app/models/user.js import Model from "ember-data/model"; import attr from "ember-data/attr"; import { belongsTo,hasMany } from "ember-data/relationships"; export default Model.extend({ name: attr("string"), password: attr("string"), birth: attr("string"), addr: attr("string"), //一對多關(guān)系,一的一方設(shè)置hasMay,多的一方設(shè)置belongsTo comments: hasMany("comment"), posts: hasMany("post") });post
// app/models/post.js import Model from "ember-data/model"; import attr from "ember-data/attr"; import { belongsTo,hasMany } from "ember-data/relationships"; export default Model.extend({ title: attr("string"), publicDate: attr("date"), content: attr("string"), user: belongsTo("user"), //一對多關(guān)系,多的一方使用belongsTo comments: hasMany("comment"), tags: hasMany("tag") });comment
// app/models/comment.js import Model from "ember-data/model"; import attr from "ember-data/attr"; import { belongsTo,hasMany } from "ember-data/relationships"; export default Model.extend({ title: attr("string"), publicDate: attr("date"), content: attr("string"), user: belongsTo("user"), //一對多關(guān)系,多的一方使用belongsTo post: belongsTo("post") });tag
// app/models/tag.js import Model from "ember-data/model"; import attr from "ember-data/attr"; import { belongsTo,hasMany } from "ember-data/relationships"; export default Model.extend({ title: attr("string"), posts: hasMany("post") });
創(chuàng)建完模型之后,先從user開始,簡單做一個列表顯示所有user,并在在列表頁面可以新增、修改、刪除user,實現(xiàn)最常見的CRUD操作。在實現(xiàn)的過程中插入adapter和serializer的內(nèi)容。
用戶列表用戶列表頁面也是很簡單的,就一個表格,其中引入了bootstrap樣式。有關(guān)怎么引入請自己網(wǎng)上找答案吧。
列表模板{{! app/templates/users/list.hbs 用戶列表}}列表路由配置{{#link-to "users.new" class="btn btn-success"}}新增{{/link-to}}
{{#each model as |user|}} 用戶名 生日 地址 操作 {{/each}} {{user.name}} {{user.birth}} {{user.addr}} {{#link-to "users.edit" user.id}}修改{{/link-to}} | 刪除
import Ember from "ember"; export default Ember.Route.extend({ model() { return this.store.findAll("user"); } });
列表的路由也很簡單,直接獲取所有的user記錄,并返回到模板中,在模板中便利出每個記錄。
待項目重啟完成,直接預(yù)覽http://localhost:4200/users/list,可以看到頁面上什么也沒有顯示,打開瀏覽器控制臺可以看到如下錯誤:
很顯然我們的項目中確實沒有提供請求http://localhost:4200/users的后端服務(wù),而且項目也沒有鏈接其他任何數(shù)據(jù)服務(wù)(比如Firebase),那么如何讓Ember項目鏈接到我自己的數(shù)據(jù)庫上呢?
在此,先引入數(shù)據(jù)服務(wù)程序,前面介紹過,本例子使用Mongodb。服務(wù)端程序請看adapter-serializer-server,對于服務(wù)端的內(nèi)容我就部過多介紹,你只需要知道這個服務(wù)程序可以接受、返回的數(shù)據(jù)格式是jsonapi就行了。然后啟動后端服務(wù)程序。
那么如何讓Ember項目鏈接到我的后端服務(wù)呢??很簡單,只需要重寫適配器的一個屬性即可。下面使用Ember CLI名稱創(chuàng)建一個適配器。
ember g adapter application
適配器創(chuàng)建完畢之后,我們直接在適配器中接入自己的后端服務(wù)。代碼如下:
// app/adapters/application.js import JSONAPIAdapter from "ember-data/adapters/json-api"; export default JSONAPIAdapter.extend({ host: "http://localhost:3000" });
http://localhost:3000是adapter-serializer-server啟動后提供服務(wù)的url。項目啟動完畢后可以看到瀏覽器控制臺的錯誤消失了!并且在“NetWork”標簽下可以看到有一個請求http://localhost:3000/users點擊這個請求,查看請求的“Response”可以看到返回的數(shù)據(jù),比如下面的數(shù)據(jù)格式:
{ "links": { "self": "http://localhost:3000/users" }, "data": [ { "id": "5753d7090280777c2381a0dd", "type": "users", "attributes": { "name": "日期修改333", "password": "11", "addr": "地址地址地址地址", "birth": "2016-06-04T00:00:00.000Z" }, "links": { "self": "http://127.0.0.1:3000/users/5753d7090280777c2381a0dd" }, "relationships": { "comments": { "data": [], "links": { "self": "http://127.0.0.1:3000/users/5753d7090280777c2381a0dd/relationships/comments" } }, "posts": { "data": [], "links": { "self": "http://127.0.0.1:3000/users/5753d7090280777c2381a0dd/relationships/posts" } } } }, { "id": "5753d74a840db09d2352608a", "type": "users", "attributes": { "name": "解決了跨域問題", "password": "123132", "addr": "范文芳啊的份水電費 測試服我飛" }, "links": { "self": "http://127.0.0.1:3000/users/5753d74a840db09d2352608a" }, "relationships": { "comments": { "data": [], "links": { "self": "http://127.0.0.1:3000/users/5753d74a840db09d2352608a/relationships/comments" } }, "posts": { "data": [], "links": { "self": "http://127.0.0.1:3000/users/5753d74a840db09d2352608a/relationships/posts" } } } }, { "id": "57545597840db09d2352608b", "type": "users", "attributes": { "name": "測試日期控件", "password": "123123", "addr": "適配器和序列化器示例" }, "links": { "self": "http://127.0.0.1:3000/users/57545597840db09d2352608b" }, "relationships": { "comments": { "data": [], "links": { "self": "http://127.0.0.1:3000/users/57545597840db09d2352608b/relationships/comments" } }, "posts": { "data": [], "links": { "self": "http://127.0.0.1:3000/users/57545597840db09d2352608b/relationships/posts" } } } } ] }
由于我項目已經(jīng)有了3條數(shù)據(jù)了,所以跟你的可能有些許不同,但是數(shù)據(jù)的格式是一致的。這個數(shù)據(jù)的格式是遵循jsonapi規(guī)范的。
上述代碼所演示的是自定義適配器最最常用的一個功能,如果你后端返回的數(shù)據(jù)是完全遵循jsonapi規(guī)范的幾乎不需要再做其他任何修改了。這樣就已經(jīng)完成自定義適配器的工作了!但是既然在此特意介紹適配器和序列化器當然不會只是介紹這一個屬性host就完了,后面將陸陸續(xù)續(xù)介紹其他的屬性,以及如何使用serializer。
繼續(xù)完成user模塊。
新增user user模板{{! app/templates/users/new.hbs 新增user}}user路由
直接在model回調(diào)中返回一個空的實例對象。方便保存。
// app/routes/users/new.js import Ember from "ember"; export default Ember.Route.extend({ model() { return this.store.createRecord("user"); }, actions: { saveUser(user) { user.save().then(() => { this.transitionTo("users.list");// 保存成功轉(zhuǎn)到列表頁面 }); } } });修改user user模板
{{! app/templates/users/edit.hbs 修改user}}user路由
在修改的方法中先調(diào)用findRecord方法查詢出被修改的數(shù)據(jù),然后更新修改的屬性,再調(diào)用save方法保存修改的內(nèi)容。
// app/routes/users/edit.js import Ember from "ember"; export default Ember.Route.extend({ // 根據(jù)ID查詢 model(params) { return this.store.findRecord("user", params.user_id); }, actions: { updateUser(user) { this.store.findRecord("user", user.get("id")).then((u) => { u.set("name", user.get("name")); u.set("addr", user.get("addr")); u.set("birth", user.get("birth")); u.set("addr", user.get("addr")); u.save(); //保存修改的屬性值 }); this.transitionTo("users.list"); //轉(zhuǎn)到列表頁面 } } });
由于新增、修改user模板都用到供一個表單,提取到一個組件中。
ember g component user-form
文件代碼就不貼出來了,有需要請點擊查看github代碼。然后在組件類中初始化了一個日期控件bootstrap-datepicker,插件直接在app/index.html中引入了,下面是組件類代碼:
// app/components/user-form.js import Ember from "ember"; export default Ember.Component.extend({ didInsertElement() { this._super(...arguments); //記得調(diào)用父類的構(gòu)造方法 //初始化日期控件 Ember.$(".datepicker").datepicker({format:"yyyy-mm-dd", autoclose: true}); } });
user列表、新增user、修改user界面效果如下截圖:
到此實現(xiàn)了類似使用Firebase的數(shù)據(jù)存儲功能,可以正確保存數(shù)據(jù)到自己的數(shù)據(jù)庫中??梢钥隙ǖ氖菙?shù)據(jù)已經(jīng)正確保存到我的MongoDB中,我就不再截圖了!對象的CRUD功能已經(jīng)實現(xiàn),后續(xù)我就不再介紹post、comment、tag的CRUD了,后續(xù)著重介紹適配器、序列化器的其他屬性以及模型之間的關(guān)聯(lián)關(guān)系(比如一對多、多對多)。
如果你認真看前面的第一個截圖你會發(fā)現(xiàn)列表上顯示的時間格式不友好,不是我們所習(xí)慣看的時間格式,那么如何處理呢?格式化時間的方式有很多,可以自定義Ember helper格式化時間,也可以定義模型user的屬性birth為date類型,在此我特意定義為了string是為了演示serializer的使用。我們可以在自定義的serializer中格式化返回的數(shù)據(jù)。下面首先創(chuàng)建serializer。
ember g serializer application
在序列化器中調(diào)用響應(yīng)請求的方法normalizeResponse格式化返回的數(shù)據(jù)。代碼如下:
// app/serializers/application.js import JSONAPISerializer from "ember-data/serializers/json-api"; export default JSONAPISerializer.extend({ // 此方法響應(yīng)請求的時候執(zhí)行 normalizeResponse(store, primaryModelClass, payload, id, requestType) { // 格式化birth的時間格式 //默認顯示的時間格式為 2016-06-09T00:00:00.000Z ,簡單處理直接截取前面的10位 // 只是為了演示方法normalizeResponse的使用,實際項目中不推薦這樣的用法,因為需要遍歷每個數(shù)據(jù),效率不好 payload.data.forEach(function(item, index) { var oldDate = item.attributes.birth; if (oldDate) { oldDate = oldDate.substring(0, 10); } item.attributes.birth = oldDate; oldDate = null; }); return this._super(...arguments); } // 此方法發(fā)送請求的時候回執(zhí)行 // serialize(snapshot, options) { // // } });
但是實際使用過程中不推薦使用這種方式格式化數(shù)據(jù),除非是不得已,因為需要遍歷每個記錄去修改屬性的值,如果數(shù)據(jù)量大影響效率,最好的方式是自定義helper在模板上格式化。把格式化的操作放到顯示數(shù)據(jù)的時候。
上述就是serializer的一個簡單實用示例。
adapter和serializer內(nèi)容比較多,分為2篇介紹,下一篇我回在本篇的基礎(chǔ)上逐個介紹adapter和serializer的常用屬性、方法的使用。
adapter與serializer使用下篇adapter與serializer使用實例二
項目源碼:https://github.com/ubuntuvim/ember-adapter-serializer
后臺源碼:https://github.com/ubuntuvim/adapter-serializer-server
有疑問歡迎在下方評論區(qū)給我留言,我會盡快為你解答,如果你覺得本文能給你幫助,或者覺得博主寫作辛苦也歡迎點擊右上角“為博主充電”給我打賞,你的肯定對我來說是最大的動力。O(∩_∩)O哈哈~
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/86351.html
摘要:返回數(shù)據(jù)請求流程后端返回的數(shù)據(jù)首先也會經(jīng)過上面的處理其次經(jīng)過返回進將數(shù)據(jù)存儲起來后返回請求數(shù)據(jù)的地方。至此一個請求后端數(shù)據(jù)的請求的流程就到此結(jié)束了。例如等以及官方推薦最少要復(fù)寫的方法 Emberjs 如何與后端服務(wù)進行交互 @[toc] 一般發(fā)送請求流程 首先來看這張圖: showImg(https://segmentfault.com/img/bVCzJn?w=339&h=521...
摘要:目前打算本項目使用種數(shù)據(jù)交互方式一種是,一種是。要理解后端服務(wù)的關(guān)系我們從他們各自的概念入手。創(chuàng)建服務(wù)端如何在項目中創(chuàng)建服務(wù)端程序呢提供了創(chuàng)建的命令。 文章來源:Ember Teach 本項目講解如何使用adapter、EmberData以及怎么連接到本地數(shù)據(jù)庫。 項目簡介 主要內(nèi)容 適配器使用 如何持久化數(shù)據(jù)到本地數(shù)據(jù)庫 簡單的后端服務(wù) 最近經(jīng)常有初學(xué)的開發(fā)者請教有關(guān)Adapte...
摘要:就沒必要動牛刀,創(chuàng)建一個數(shù)據(jù)庫了執(zhí)行完后,在目錄下創(chuàng)建一個程序,自動植入到當前項目中,訪問的和與訪問域名端口一致。就沒必要動牛刀,創(chuàng)建一個數(shù)據(jù)庫了本篇博文將為你介紹如何使用實現(xiàn)權(quán)限控制,我會創(chuàng)建一個簡單的登錄示例加以說明。 文章來源:http://blog.ddlisting.com 官網(wǎng)對于登錄、用戶權(quán)限的介紹只有一段簡單的說明,并沒有詳細說明如何使用service實現(xiàn)權(quán)限控制。下面...
摘要:遠程調(diào)用開篇目標介紹之后解讀遠程調(diào)用模塊的內(nèi)容如何編排介紹中的包結(jié)構(gòu)設(shè)計以及最外層的的源碼解析。十該類就是遠程調(diào)用的上下文,貫穿著整個調(diào)用,例如調(diào)用,然后調(diào)用。十五該類是系統(tǒng)上下文,僅供內(nèi)部使用。 遠程調(diào)用——開篇 目標:介紹之后解讀遠程調(diào)用模塊的內(nèi)容如何編排、介紹dubbo-rpc-api中的包結(jié)構(gòu)設(shè)計以及最外層的的源碼解析。 前言 最近我面臨著一個選擇,因為dubbo 2.7.0-...
閱讀 3498·2021-09-08 10:46
閱讀 1192·2019-08-30 13:17
閱讀 2372·2019-08-30 13:05
閱讀 1214·2019-08-29 15:29
閱讀 2893·2019-08-29 11:31
閱讀 548·2019-08-26 12:13
閱讀 1544·2019-08-26 11:42
閱讀 1850·2019-08-23 18:37