亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 網站 > WEB開發 > 正文

Ember Model

2024-04-27 15:07:43
字體:
來源:轉載
供稿:網友

model是指數據層,也就是一個用于向用戶展示的數據對象??紤]到前后端分離,其實可以認為展現內容與后端的DTO對象或者DVO對象是一一對應的。同時,model會通過json的形式以http請求的方式與服務器進行交互。但是,model的形式不一定是json的,其他的形式都是可以的。也就是說,model是持久化的。

這種方式下,ember本身提供了許多api,這也就是Ember data做的事情。Ember Data為你提供了更加簡便的方式操作數據,統一管理數據的加載,降低程序復雜度。

Ember Data有幾個重要的概念,分別為:models、records、adapters、store、serializer.

models

個人認為,model這個類,應該和后端的DO或者是DTO對象是一一對應的。 model的定義,可以通過命令行方式: ember g model <your-model-name> 則會創建一個app/models/<your-model-name>.js的文件。其中就是model的主體,由若干個屬性構成,如:

export default DS.Model.extend({ title: DS.attr('string'), // 字符串類型 flag: DS.attr('boolean'), // 布爾類型 timestamp: DS.attr('number'), // 數字類型 birth: DS.attr('date'), //日期類型 addr: DS.attr(), //json類型,其實就是string});

這里需要注意,沒有id字段,Ember 會默認生成id屬性。 如果有對應關系的話,比如一對多或者多對一的情況,那么可以使用Ember Data中的hasMany 以及 belongsTo方法。belongsTo為一對一關系,hasMany為一對多關系。使用方式如下

import DS from 'ember-data';//app/models/blog-post.jsexport default DS.Model.extend({ comments: DS.hasMany('comment')});//app/models/commont.jsexport default DS.Model.extend({ blogPost: DS.belongsTo('blog-post')});

如果是多對多的關系,則如下就好:

import DS from 'ember-data';//app/models/blog-post.jsexport default DS.Model.extend({ comments: DS.hasMany('comment')});//app/models/commont.jsexport default DS.Model.extend({ blogPost: DS.hasMany('blog-post')});

這個對應關系,可以看做為,實際的邏輯表之間的對應關系。

此外,還可以添加計算屬性,因為,model也是一個Ember Object

export default DS.Model.extend({ title: DS.attr('string'), // 字符串類型 flag: DS.attr('boolean'), // 布爾類型 tf: Ember.computed('title', 'flag', function() { return `${this.get('title')} ${this.get('flag')}`; })});

store & record

store這個概念,在Ember Data中十分重要。 store是指所有的從服務端活動的record的數據以及新創建的record數據。即,store為所有數據的緩存,所有關于record的增刪改查動作,都需要經過store。

一般情況下,一個應用,只有一個DS.store,它是由Ember.application初始化的。

record是指一個model的實例,他可能是一個從服務端返回的數據,當然,你自己也可以新建一個record。

假設我們有一個route:

// app/routes/store-route.jsimport Ember from 'ember';export default Ember.Route.extend({ model: function() { }});

store 這個概念,可以在route以及controller中使用。形如this.get('store') 或者 this.store。

查詢record

(1)store.findRecord() 通過model的type以及id,發起一個請求,去獲取數據,他返回一個PRomise對象,結果為record。

model(){ return this.store.findRecord('model-example',1).then((data) => { return data; }); //get請求為 域名/model-examples/1, 例如 http://localhost:4200/model-examples/1}

(2)store.peekRecord(), 通過model的type以及id,不發起一個請求,從store中去獲取現有以加載的數據。

model(){ return this.store.peekRecord('model-example',1); //無請求}

(3)store.findAll(), 通過model的type獲取所有的數據,發起請求,返回的為,DS.PromiseArray對象,結果為DS.RecordArray

model(){ return this.store.findAll('model-example').then((data)=>{return data}); //get請求為 域名/model-examples, 例如 http://localhost:4200/model-examples}

(4)store.peekAll(), 通過model的type獲取所有的數據,不發起請求,從store中去獲取現有以加載的數據,返回的為DS.RecordArray

model(){ this.store.findAll('model-example'); //無請求}

這里需要注意,DS.RecordArray,并不是一個[]它使一個可遍歷的對象。這意味著,如果你在模板中,使用了這些reocrd,那么就可以享受到雙向綁定的好處,同時,也提供了一些API,能夠幫助你更方便的使用。具體可參考:Ember.js DS.Store

(5)store.query()條件查詢,查詢條件為type以及自定義條件,同樣也是一個get請求,返回結果通store.findAll()

model(){ this.store.query('model-example',{firstName:'James'}); //get 請求,請求為 域名/model-examples?firstName=James,例如,http://localhost:4200/model-examples?firstName=James}

(6)store.queryRecord()條件查詢,查詢條件為type以及自定義條件,同樣也是一個get請求,返回結果同store.findRecord()

model(){ this.store.queryRecord('model-example',{firstName:'James'}); //get 請求,請求為 域名/model-examples?firstName=James,例如,http://localhost:4200/model-examples?firstName=James,返回結果為promise,其中為一個record}

創建record

使用store.createRecord()來增加一個record。

model(){ let a = this.store.createRecord('model-example',{ firstName:'firstName', secondName: 'secondName' }); return a;}

則返回一個record。

在運用場景上,我們可以設想這樣一個場景,比如一個表單:

//route route-example.hbs<form class="" action="index.html" method="post"> firstName:{{input value=model.firstName}} secondName:{{input value=model.secondName}} <button type="submit" name="button" {{action 'submitForm'}}>提交</button></form>//route route-example.jsimport Ember from 'ember';export default Ember.Route.extend({ model(){ return this.store.createRecord('model-example',{ firstName:'', secondName: '' }); }, actions:{ actionSubmit(){ let model = this.modelFor('route-example'); model.save(); //這里會發出一個post請求,即 域名/model-example, 這里是localhost:8000/model-example,參數為{"data":{"attributes":{"first-name":"<你填寫的內容>","second-name":"<你填寫的內容>"},"type":"model-examples"}} } }});

生成的頁面如下: 這里寫圖片描述

這的數據是一個雙向綁定的過程,在頁面上的變動會直接變化到model上。

更新record

更新record的操作也是一樣的

this.store.findRecord('model-example', 1).then(function(data) { data.set('firstName', "name1");});

這樣就可以對其進行修改。

持久化record

持久化,也就是說將數據存入數據庫,實際上是一個與后端進行交互的過程。 調用sava()方法就可以。 但是不同于新建的post請求,所有更新操作的請求為PATCH請求。

this.store.findRecord('model-example', 1).then(function(data) { data.set('firstName', "name1"); data.save() //patch 請求:域名/model-examples/1, 在這里為:http://localhost:4200/model-examples/1 //參數 {"data":{"id":"1","attributes":{"firstName":"asdas","secondName":"sn"},"type":"model-examples"}}});

刪除record

使用deleteRecord()可以刪除一個record

this.store.findRecord('model-example', 1).then(function(data) { data.deleteRecord(); data.get('isDeleted');//true =>表示已經刪除});

如果想要持久化到后端,調用sava()

this.store.findRecord('model-example', 1).then(function(data) { data.deleteRecord(); data.get('isDeleted');//true =>表示已經刪除 data.save();//這會發送一個DELETE請求,為 http://localhost:4200/model-examples/1});

或者直接調用

this.store.findRecord('model-example', 1).then(function(data) { data.destroyRecord();//這會發送一個DELETE請求,為 http://localhost:4200/model-examples/1});

插入record

ember還支持直接向store中插入record,但是這個過程不是與后端交互的過程。是通過push()方法實現的。

//route route-example.jsexport default Ember.Route.extend({ model() { this.get('store').push({ data: [{ id: 1, type: 'model-example', attributes: { firstName: 'fn1', secondName: 'sn1', }, }, { id: 1, type: 'model-example', attributes: { firstName: 'fn1', secondName: 'sn1', }, }] }); }});

這樣就可以手動向其中插入兩條record。例如,當時不想用他提供的方式如post、patch、delete進行增刪改數據,那么可以使用Ajax先更新或者插入數據,然后在手動push進store。

小結

總結一下增刪改查的請求形式: //TODO

adapters

適配器,決定了數據如何持久化到后端。舉例而言,請求的URL、REST API的header等。 創建適配器的命令,同樣通過命令行就可以創建:ember g adapter <your-adapter-name>。這里注意,這里的名字必須和路由的是一致的,關于路由的規則,我們后面獨立說。 以application這個路由為例,其適配器配置可能為:

//app/adapters/application.jsimport DS from 'ember-data';export default DS.JSONAPIAdapter.extend({ host: 'http://xxx.com', namespace: 'api/v1', pathForType: function(type) { return Ember.String.underscore(type); }, headers: { 'API_KEY': 'secret key', 'ANOTHER_HEADER': 'Some header value' }});

下面解釋一下這幾個常用規則的配置:

host,指域名namespace,命名空間,如上述的情況下,model名為model-example的新建請求為(忽略pathForType方法):http://xxx.com/api/v1/model-examplepathForType,修改model的適配方式,如果你希望都是下劃線的方式,可以調用Ember.String.underscore()方法,就可以把駝峰或者中劃線改為下劃線,那么上述的情況下,新建的請求為:http://xxx.com/api/v1/model_exampleheaders,http的heads,這里是支持計算屬性的,例如:export default DS.JSONAPIAdapter.extend({ session: Ember.inject.service('session'), headers: Ember.computed('session.authToken', function() { return { 'API_KEY': this.get('session.authToken'),//這里的headers取自session的authToken字段 'ANOTHER_HEADER': 'Some header value' }; })});

在適配器中,你還可以重寫函數findRecord() findAll……等等:

export default DS.JSONAPIAdapter.extend({ findRecord(store, type, id){ return Ember.$.getJson(`${this.get('host')}/${this.get('namespace')}/${type}/${id}`); }});

序列化器serializers

序列化器serializers主要負責用來格式化數據。這個在Ember Data中十分重要,因為本身model的數據格式十分蛋疼,用起來非常難受。

創建serializers,也可以是命令行工具:ember g serializer <your-serializer-name>

Ember Data提供了3種serializers的默認實現,分別為:

JSONAPISerializer,2.0以后版本的默認實現JSONSerializer 針對單個json或者json array的簡單實現RESTSerializer2.0以前版本的默認實現,較為復雜,可以支持邊緣加載,即是通過增加數據層級來分步加載(可以理解為先加載第一層次的數據集合,然后按需加載子一級的數據集合)

這意味著,根據自己的需求,繼承其中任意一個類就可以。

現在考慮標準格式的record:

//單條record{ "data": { "type": "people", "id": "123", "attributes": { "first-name": "Jeff", "last-name": "Atwood" } }}//recordArray{ "data": [{ "type": "model-example", "id": "1", "attributes": { "firstName": "Jeff", "secondName": "Atwood" } }, { "type": "model-example", "id": "2", "attributes": { "firstName": "Yehuda", "secondName": "Katz" } }]}//如果數據除了本身之外還有關系數據,那么關系數據就放在`included`中{ "data": { "type": "articles", "id": "1", "attributes": { "title": "JSON API paints my bikeshed!" }, "links": { "self": "http://example.com/articles/1" }, "relationshxml better" }, "links": { "self": "http://example.com/comments/12" } }]}

我們從簡單的情況入手,比如,正常情況下,我們的后端返回的數據格式可能為:

{ "result":[ { "id": 1, "firstName": "Jeff", "secondName": "Atwood" }, { "id": 1, "firstName": "Yehuda", "secondName": "Katz" } ]}

這種情況下,如果返回的話,前端一定會報錯,因為格式不匹配,找不到data。

格式化內容數據

import DS from 'ember-data';export default DS.JSONAPISerializer.extend({ normalizeResponse(store, primaryModelClass, payload, id, requestType) { if (payload) { if (!payload.result){ let documentHash = {included:[]}; if(id) documentHash.data=null; else documentHash.data=[]; return documentHash; } return this._super(store, primaryModelClass, payload.result, id, requestType); } return this._super(...arguments); },});

這樣,就可以將返回的result轉化為data。

反之,如果請求中,后端需要的內容與前端給的不一樣,只需要重寫serialize方法:

import DS from 'ember-data';export default DS.JSONSerializer.extend({ serialize: function(snapshot, options) { var json = this._super(...arguments); // ?? json.data.attributes.cost = { amount: json.data.attributes.amount, currency: json.data.attributes.currency }; delete json.data.attributes.amount; delete json.data.attributes.currency; return json; }});

通過上述的方式,可以把前端發送的內容:

{ "data": { "attributes": { "id": "1", "name": "My Product", "amount": 100, "currency": "SEK" }, "type": "product" }}

變為:

{ "data": { "attributes": { "id": "1", "name": "My Product", "cost": { "amount": 100, "currency": "SEK" } }, "type": "product" }}

最后說兩句,RESTSerializer的實現與其他兩個不同,他沒有規定返回的格式,也就是說可以是任意格式的,而其他的都是json。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产丝袜高跟一区| 久久久国产一区二区三区| 色偷偷91综合久久噜噜| 日韩中文字幕国产| 操人视频在线观看欧美| 欧美人与性动交| 亚洲成人激情视频| 日韩视频免费观看| 欧美成人精品在线播放| xxxxx成人.com| 成人久久一区二区| 日韩欧美亚洲一二三区| 日韩国产高清污视频在线观看| 91在线网站视频| 欧美视频在线视频| 中文字幕一区日韩电影| 亚洲国产精品久久久| 日韩美女激情视频| 亚洲精品福利资源站| 亚洲品质视频自拍网| 欧美第一淫aaasss性| xxxxx成人.com| 欧美老女人xx| 色综合久久中文字幕综合网小说| 青青青国产精品一区二区| 日韩免费不卡av| 日韩亚洲成人av在线| 日本久久久久久久久| 日本久久精品视频| 欧美成人激情视频| 亚洲国产精品悠悠久久琪琪| 性色av一区二区三区红粉影视| 久久免费视频在线| 国产精品自拍偷拍| 欧美性猛交xxxx乱大交蜜桃| 最近2019年好看中文字幕视频| 在线观看久久久久久| 国产色视频一区| 自拍偷拍免费精品| 欧美日韩美女在线| 午夜剧场成人观在线视频免费观看| 欧洲精品毛片网站| 国产精品女人网站| 亚洲在线观看视频网站| 亚洲国产成人久久综合| 国模精品系列视频| 91老司机精品视频| 国产亚洲精品久久久久久| 色综合天天综合网国产成人网| 美女少妇精品视频| 亚洲综合一区二区不卡| 欧美疯狂性受xxxxx另类| 久久久免费精品视频| 国产日韩亚洲欧美| 九九视频这里只有精品| 91精品91久久久久久| 欧美日韩一二三四五区| 欧美久久精品午夜青青大伊人| 国内成人精品视频| 亚洲免费影视第一页| 成人精品一区二区三区电影免费| 欧美巨乳美女视频| 911国产网站尤物在线观看| 欧美精品成人91久久久久久久| 久久99国产精品久久久久久久久| 日韩av成人在线观看| 欧美国产日韩中文字幕在线| 亚洲精品在线视频| 国产色婷婷国产综合在线理论片a| 日本精品视频在线观看| 亚洲视频在线视频| 91麻豆桃色免费看| 色综合91久久精品中文字幕| 久久久久免费精品国产| 亚洲人午夜色婷婷| 国产日韩换脸av一区在线观看| 日韩精品免费综合视频在线播放| 亚洲人成在线免费观看| 久久国产天堂福利天堂| 欧美在线视频在线播放完整版免费观看| 国产精品一二三视频| 国产精品扒开腿做| 欧美激情极品视频| 亚洲尤物视频网| 亚洲已满18点击进入在线看片| 亚洲欧美成人在线| 亚洲精品国产精品国自产观看浪潮| 国产日韩在线一区| 欧美激情女人20p| 日韩人体视频一二区| 国产精品一区二区三区毛片淫片| 亚洲桃花岛网站| 91chinesevideo永久地址| 日韩一区二区三区在线播放| 亚洲男人的天堂在线播放| 欧美精品在线免费观看| 欧美大片va欧美在线播放| 亚洲欧美精品suv| 91亚洲人电影| 美女国内精品自产拍在线播放| 91亚洲永久免费精品| 久久精品美女视频网站| 国产91精品黑色丝袜高跟鞋| 在线电影欧美日韩一区二区私密| 亚洲国产精品资源| 欧美中文在线观看国产| 91在线免费看网站| 国产成人精品电影久久久| 亚洲aⅴ日韩av电影在线观看| 亚洲第一区第一页| 国产一区av在线| 欧美成人精品h版在线观看| 国产色婷婷国产综合在线理论片a| 日本91av在线播放| 欧美疯狂做受xxxx高潮| 亚洲精品一区二区网址| 国产精品极品尤物在线观看| 久久精品99无色码中文字幕| 国产成人精品视频在线观看| 欧美成人四级hd版| 亚洲激情视频网站| 92版电视剧仙鹤神针在线观看| 亚洲丝袜在线视频| 国产不卡一区二区在线播放| 欧美午夜性色大片在线观看| 97视频在线观看视频免费视频| 成人激情在线播放| 亚洲男人天天操| 国产精品pans私拍| 久久久精品一区二区| 成人免费自拍视频| 日日噜噜噜夜夜爽亚洲精品| 国产成人久久久| 欧美xxxx做受欧美| 91成人性视频| 尤物九九久久国产精品的特点| 欧美在线视频观看免费网站| 国产va免费精品高清在线| 久久久噜噜噜久久中文字免| 日韩高清av一区二区三区| 操91在线视频| 欧美亚洲另类视频| 亚洲人成电影网站色www| 欧美精品在线视频观看| 久久精品国产69国产精品亚洲| 久久综合九色九九| 久久人人爽人人| 久久久久久这里只有精品| 日韩久久午夜影院| 亚洲xxxxx电影| 久久久久久这里只有精品| 国产成人精品一区二区三区| 亚洲欧美制服中文字幕| 欧美一区第一页| 国产视频丨精品|在线观看| 国外成人性视频| 亚洲国产日韩一区| 色吧影院999| 亚洲欧美www| 色诱女教师一区二区三区| 91久久久国产精品| 国产精品激情av在线播放| 久久电影一区二区| 欧美一级黑人aaaaaaa做受|