摘要:目前打算本項目使用種數據交互方式一種是,一種是。要理解后端服務的關系我們從他們各自的概念入手。創建服務端如何在項目中創建服務端程序呢提供了創建的命令。
文章來源:Ember Teach
本項目講解如何使用adapter、EmberData以及怎么連接到本地數據庫。
項目簡介 主要內容適配器使用
如何持久化數據到本地數據庫
簡單的后端服務
最近經常有初學的開發者請教有關Adapter或者Ember Data的問題。官方教程中講到這兩個內容的是Model這一章節。本文中介紹到的內容大部分是由這一章來的,如果有不妥請看原文或者給我留言。
注意:本文是基于v2.6.0講解。
軟件需求MySQL
nodejs,express
body-parser
mysql-node
Ember項目常規運行軟件Git
Node.js (with NPM)
Bower
Ember CLI
PhantomJS
用到的軟件、插件都是有關后端服務的,mysql-node用于連接、操作MySQL數據庫。后端服務是用node寫的所以也用node項目的插件連接、操作數據庫了,有關如何使用node操作MySQL的信息請看這篇文章[nodejs連接MySQL,做簡單的CRUD
](http://blog.ddlisting.com/201...。如果你的后端是其他語言寫只需要保證你后端返回的數據格式或者我的后端返回的數據格式一致就行了。目前打算本項目使用2種數據交互方式:一種是jsonapi,一種是restapi。
jsonapi
rest api
項目搭建項目的搭建就不再費口舌了,Ember Teach已經有很多博文介紹過了。
運行項目如果你想運行本項目請按照下面的步驟操作:
安裝下載代碼到本地 git clone https://github.com/ubuntuvim/emberData-adapter-database
進入項目目錄 cd emberData-adapter-database
安裝npm依賴包 npm install
安裝bower依賴包 bower install
運行在項目目錄下執行命令 ember server 運行項目。
待項目啟動完畢,在瀏覽器打開http://localhost:4200。
發布到服務器執行命令編譯、打包項目 ember build --environment production
命令執行完畢會在dist目錄下得到項目打包后的文件。
把打包后的dist目錄下的所有文件復制到服務器應用目錄下運行即可(比如tomcat服務器則放到webapps目錄下)。
項目結構簡單起見我就做一個頁面就行了,我希望做出的效果是使用自定義的適配器獲取到本地MySQL數據庫的數據并分頁展示。
創建文件使用ember-cli命令創建文件。
ember g route users ember g model user username:string email:string ember g adapter application
目前暫時只用到這幾個文件,后續可能還有其他的用到在創建。
ember g model user username:string email:string的作用是創建模型的同時創建2個屬性,并且屬性都指定為string類型。
說了一大堆廢話下面開始正題。要理解adapter、ember data、后端服務的關系我們從他們各自的概念入手。首先我們先理清楚他們之間的關系然后在動手實踐。理論總是繁瑣的但是也是最重要的。
========================= 華麗的分割線 =========================
體系結構概述注:圖片來自官方文檔
注意觀察上圖的結構。
APP(一般是從route、controller或者component發請求)請求數據。
請求并沒有直接發送到后端服務而是先在store(ember data其實就是一個store)緩存中查找,ember之所以能實現動態更新模板數據也是因為有了store。
如果請求的數據存在在store中,則直接返回到route、controller或者component;如果在store中沒有發現請求的數據,所以請求的數據是首次,數據還未緩存到store中,則請求繼續往下到了apdater層。
在adapter中,adapter會根據請求的調用方法構建出對應的URL。比如在route、controller或者component中執行方法findRecord("user", 1),此方法作用是查詢id為1的user數據。適配器構建出來的URL為: http://domain/user/1,然后發請求到后端。
適配器會對比后端接受的數據格式與ember data發送的數據格式,如果不一致需要在適配器的``方法中格式化發送的數據格式。請求經過適配器構建得到URL后發送到后端服務,后端服務根據URL請求查詢數據庫然后格式化數據格式返回到適配器。
適配器根據得到的數據和ember data所接受的數據格式匹配,如果格式不一致需要在適配器的``方法中格式化后端返回的數據。
經過適配器之后數據轉到ember data(store)中,首先緩存到store中,然后返回到調用處(route、controller、component)
數據請求完畢
注意:findRecord("user", 1)方法執行過程,請求的findRecord("user", 1)方法會在Ember Data內部解析為find方法,find方法會首先在store緩存中查數據,如果沒有則會流轉到adapter中組裝URL并格式化請求數據,然后發送到后端服務。
從圖中看到從適配器返回的數據是promise所以調用findRecord方法獲取數據的時候需要then()。同時可見這是個移步請求,只有promises執行成功才能得到數據。也就是說如果考慮周全的話還需要在findRecord的時候處理promises執行失敗的情況。
另外如果你想跳過store不需要這層緩存也是可以的。會可以這樣做:store.findRecord(type, id, { reload: true })使用reload屬性設置為true讓每次請求都跳過store直接發送請求到后端,對于實時性要求高的APP則需要這樣處理。
介紹完架構之后將追個介紹其中的每個主要的功能特性。
需要說明的是:Models, records, adapters以及store都是Ember Data最核心的東西,他們是包含的關系,只要使用了Ember Data才能使用model、store功能。有些初學者老是問這幾個東西的關聯,希望看到這里的同學不要在提這樣的問題了!!=^=
Ember Data是Ember.js非常重要的一塊,提供了幾乎所有操作數據的API,詳細請看EMBER-DATA MODULE。當然,如果你不想使用Ember Data也是可以的,那么你的程序直接使用Ajax與后臺交互也是可以的,或者說你使用其他類似Ember Data的插件也行。Ember Data在MVC模式中屬于M層的東西,沒有這層也并不影響到整個APP!
補充一下下如果你不使用Ember Data,在這里提供一個簡單的方案供參考。
如果你想獲取后端數據并顯示數據到組件上(模板調用組件),你可以像下面的代碼這樣處理:
// app/components/list-of-drafts.js export default Ember.Component.extend({ willRender() { $.getJSON("/drafts").then(data => { this.set("drafts", data); }); } });
這里不同過Ember Data,自然也就沒有調用Ember Data提供的方法(比如,findAll、findRecord),而是直接發Ajax請求,得到數據到設置到對象drafts中,然后在模板上顯示數據。
這樣處理是沒問題的,但是當數據改變的可能不能立即在模板上更新,因為這里無法使用store自然也就無法像計算屬性那樣當數據有變就立即更新模板。另一個問題是當你的請求很多的時候你需要寫很多這樣的方法,代碼復用性也比較差。
ModelsIn Ember Data, each model is represented by a subclass of Model that defines the attributes, relationships, and behavior of the data that you present to the user.
從使用上講,model其實就是與后端數據表對應的實體類(借用java中的說法),通常我們的model類的定義是與后端數據表對應的,最常見的就是model屬性的定義,建議屬性名和數據表字段名一致并且使用駝峰式命名規范。
model之間還可以定義單向或者雙向的一對一、一對多和多對多關系,這個與數據表之間的關系定義是相似的。比如下面的model:
簡單model定義//app/models/person.js import Model from "ember-data/model"; import attr from "ember-data/attr"; export default Model.extend({ firstName: attr("string"), birthday: attr("date") });
model類可以直接使用ember-cli命令創建:
ember g model person
上面代碼創建了一個簡單的model,并且包含了3個屬性,一個是string類型一個是date類型,那么第三個屬性是什么了??是id,Ember會默認為每個model增加一個屬性id,開發者不需要手動去定義這個屬性,并且如果你是手動在model類中定義這個屬性會報錯的!!那么對應后端的服務也應該有一個person表,并且表里也有三個字段,它們是firstName、birthday以及id。
更多有關model之間關系的介紹不行本文的重點,請看第六章 模型的詳細介紹。
有了model之后程序要使用model類必須要實例化,實例化的model稱為records。
RecordsA record is an instance of a model that contains data loaded from a server. Your application can also create new records and save them back to the server. A record is uniquely identified by its model type and ID.
簡單講record就是一個包含數據的model實例。說白了就是一個JSON對象(雖然這樣的說法不是很正確,但是可以反映出這是一個什么樣的對象結構)。
比如下面的代碼:
this.get("store").findRecord("person", 1); // => { id: 1, name: "steve-buscemi" }
執行完方法findRecord后返回的就是一個model實例也就是一個record。這個record包含了數據{ id: 1, name: "steve-buscemi" }。
AdapterAn adapter is an object that translates requests from Ember (such as "find the user with an ID of 123") into requests to a server.
適配器,顧名思義!作用就是做適配工作的,保存轉換數據格式、定義交互的URL前綴、構建URL等等。在前面體系結構已經詳細介紹過,不在贅述。
Caching緩存在Ember中是非常重要的,但是有一點需要注意的是不要把太多數據緩存到store中,數據量太大瀏覽器受不了!緩存的作用是非常明顯的,前面也介紹了他的作用,特別是在請求數據的時候,如果能在緩存中獲取的則立即返回到調用處,只有在緩存中查不到的數據才發請求到服務端,通常是第一次獲取的數據的時候緩存沒有則需要發請求到服務端。也正是有了緩存Ember才能快速把數據的變化響應到模板上。
到此主要核心的概念介紹完畢了,不算多,但是認真看下來還是很有益的!!
下面接著是如何實踐了……
創建數據庫本例子使用的是MySQL數據庫,有關數據庫的安裝以及使用不在本文講解范圍,請自行學習!
建表怎么建表我也不說了,下面直接貼建表的SQL。
DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(100) DEFAULT NULL, `email` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
創建一個名為user的數據表。
創建服務端如何在ember項目中創建服務端程序呢?ember提供了創建的命令。
ember g server
創建完畢之后再按照開始介紹的依賴插件。
npm install mysql-node npm install body-parser npm install supervisor
創建的是一個node服務端程序,運行的端口也是4200,不需要另外手動去啟動node服務,只要ember項目運行了會自動運行起來的。
到此所有的原料都準備好了,下面驗證一下項目是否還能正常運行。啟動項目,然后在瀏覽器打開http://localhost:4200。還能看到Welcome to Ember說明是成功的!
有了原料開始做菜吧!!!
編寫user模塊 更改URL方式為了不使服務端和Ember請求URL沖突修改了URL的默認方式,修改config/environment.js的第8行代碼為如下:
locationType: "hash",
auto改為hash。訪問Ember項目的URL則需要注意:http://localhost:4200/users改為http://localhost:4200/#/users。增加一個#號。
獲取數據、顯示數據首先簡單列出數據庫數據。
用戶列表
# | 用戶名 | 郵箱 |
---|---|---|
{{user.id}} | {{user.username}} | {{user.email}} |
// app/routes/users.js import Ember from "ember"; export default Ember.Route.extend({ model() { return this.store.findAll("user"); } });
目前項目還沒連接到任何數據庫,也沒有使用自定義的適配器,如果直接執行http://localhost:4200/#/users可以在控制臺看到是會報錯的。那么下一步該如何處理呢??
加入適配器 使用RESTAdapter先從適配器下手!在前面已經創建好了適配器,如果是2.0之后的項目默認會創建JSONAPIAdapter這個適配器所接收、發送的數據格式都必須符合jsonapi規范,否則會報錯,無法正常完成數據的交互。不過為了簡便我們先不使用這個適配器,改用另一個簡單的適配器RESTAdapter,這個適配器不是需要遵循jsonapi規范,只要自己約定好前后端的數據格式即可。
// app/adapters/application.js // import JSONAPIAdapter from "ember-data/adapters/json-api"; import DS from "ember-data"; export default DS.RESTAdapter.extend({ });
手動修改好之后的適配器還不能起作用,這個適配器并沒有連接到任何的后端服務,如果你想連接到你的服務上需要使用屬性host指定。
// app/adapters/application.js // import JSONAPIAdapter from "ember-data/adapters/json-api"; import DS from "ember-data"; export default DS.RESTAdapter.extend({ host: "http://localhost:4200" });
等待項目重啟完畢,仍然是訪問http://localhost:4200/#/user,在控制臺仍然看到前面的錯誤,截圖如下:
為何還是錯誤呢?如果能看到錯誤說明你的程序是正確,到目前為止還沒提供任何的后端服務,雖然前面使用ember g server創建了node后端服務,但是并沒有針對每個請求做處理。當你訪問路由user在進入回到model時候會發送請求獲取所有模型user數據,請求首選轉到Ember Data(store),但是在store中并沒有,然后請求繼續轉到適配器RESTAdapter,適配器會構建URL得到GET請求http://localhost:4200/users,至于是如何構建URL的請看build url method。這個請求可以在報錯的信息中看到。但是為何會報錯呢?很正常,因為我的后端服務并沒響應這個請求。下面針對這個請求做處理。
修改server/index.js。
/*jshint node:true*/ // To use it create some files under `mocks/` // e.g. `server/mocks/ember-hamsters.js` // // module.exports = function(app) { // app.get("/ember-hamsters", function(req, res) { // res.send("hello"); // }); // }; module.exports = function(app) { var globSync = require("glob").sync; var mocks = globSync("./mocks/**/*.js", { cwd: __dirname }).map(require); var proxies = globSync("./proxies/**/*.js", { cwd: __dirname }).map(require); // Log proxy requests var morgan = require("morgan"); app.use(morgan("dev")); // 對象轉json // const serialise = require("object-tojson") const bodyParser = require("body-parser"); mocks.forEach(function(route) { route(app); }); proxies.forEach(function(route) { route(app); }); app.use(bodyParser.urlencoded({ extended: true })); // 處理請求 http://localhost:4200/user app.get("/users", function(req, res) { // 返回三個對象 res.status(200).send({ users: [ { id: 1, username: "ubuntuvim", email: "123@qq.com" }, { id: 2, username: "ddlisting.com", email: "3333@qq.com" }, { id: 3, username: "www.ddlising.com", email: "1527254027@qq.com" } ] }); }); };
在服務端增加了一個node請求處理,攔截/users這個請求。對于express不是本文的重點,請自行學習,網址expressjs.com。如果你使用的是其他語言的服務端程序,那么你只需要返回的json格式為:{"modelName":[{"id":1,"屬性名":"屬性值","屬性名2":"屬性值2"},{"id":2,"屬性名3":"屬性值3","屬性名4":"屬性4"}]},只需要格式正確適配器就能正確解析返回的數據。
另外再多介紹一個屬性namespace,這個屬性是用于定義URL前綴的,比如下面的適配器定義:
// app/adapters/application.js // import JSONAPIAdapter from "ember-data/adapters/json-api"; import DS from "ember-data"; export default DS.RESTAdapter.extend({ namespace: "api/v1", host: "http://localhost:4200" });
如果是這樣定義那么后端處理的URL也需要做相應的處理,需要在攔截的請求上加前綴,比如下面的代碼。
// 處理請求 http://localhost:4200/api/v1/user app.get("/api/v1/users", function(req, res) { // 返回三個對象 res.status(200).send({ users: [ { id: 1, username: "ubuntuvim", email: "123@qq.com" }, { id: 2, username: "ddlisting.com", email: "3333@qq.com" }, { id: 3, username: "www.ddlising.com", email: "1527254027@qq.com" } ] }); });
之前面唯一不同的就是請求的URL不一樣了,原來是http://localhost:4200/users改為http://localhost:4200/api/v1/users。那么這樣做的好處是什么呢?當你的后端的API更新的時候這個設置是非常有用的,只需要設置命名前綴就能適應不用版本的API。
項目重啟之后,再次進入到路由users可以看到返回的3條數據。如下截圖:
到此,我想你應該知道個大概了吧!!更多有關適配器的介紹請看下面的2篇博文:
adapter與serializer使用示例一
adapter與serializer使用示例二
使用JSONAPIAdapter使用JSONAPIAdapter適配器和使用RESTAdapter適配器有何不同呢?我覺得最重要的一點是:數據規范。JSONAPIAdapter適配器要求交互的數據格式必須遵循jsonapi規范,否則是不能完成數據交互的。要求高了相應的你的處理代碼也相應的要復雜。下面我們改用JSONAPIAdapter處理。
// app/adapters/application.js import JSONAPIAdapter from "ember-data/adapters/json-api"; import DS from "ember-data"; // export default DS.RESTAdapter.extend({ export default JSONAPIAdapter.extend({ namespace: "api/v1", host: "http://localhost:4200" });
修改適配器為JSONAPIAdapter。如果你不修改后端的服務那么控制臺可以看到報錯信息。
從截圖當中可以清楚地看到報錯出來的錯誤,must return a valid JSON API document必須是一個有效jsonapi文檔。要修復好這個錯誤也很簡單,只需要滾吧后端服務返回的數據格式改成jsonapi的就行了。請看下面的代碼:
// 處理請求 http://localhost:4200/user app.get("/api/v1/users", function(req, res) { // 返回三個對象 // res.status(200).send({ // users: [ // { // id: 1, // username: "ubuntuvim", // email: "123@qq.com" // }, // { // id: 2, // username: "ddlisting.com", // email: "3333@qq.com" // }, // { // id: 3, // username: "www.ddlising.com", // email: "1527254027@qq.com" // } // ] // }); // 構建jsonapi對象 var input = { data: [ { id: "1", type: "user", //對應前端程序中模型的名字 attributes: { // 模型中的屬性鍵值對 username: "ubuntuvim", property: true, email: "123@qq.com", property: true } }, { id: "2", type: "user", //對應前端程序中模型的名字 attributes: { // 模型中的屬性鍵值對 username: "ddlisting.com", property: true, email: "3333@qq.com", property: true } }, { id: "3", type: "user", //對應前端程序中模型的名字 attributes: { // 模型中的屬性鍵值對 username: "www.ddlising.com", property: true, email: "1527254027@qq.com", property: true } } ] }; res.status(200).send(JSON.stringify(input)); });
注:為了構建jsonapi對象更加簡便另外在安裝一個插件: npm install jsonapi-parse。安裝完畢后手動關閉再重啟項目。然后再次進入路由users可以看到與前面的結果一樣,正確了顯示后端返回的數據。
到此,我相信讀者應該能明白這兩個適配器之間的差別了!需要注意的是Ember.js2.0版本之后JSONAPIAdapter作為默認的適配器,也就是說平常如果你沒有自定義任何適配器那么Ember Data會默認使用的是JSONAPIAdapter適配器。所以如果你沒有使用其他的適配器那么你的后端返回的數據格式必須是遵循jsonapi規范的。另外在路由users.js中使用到Ember Data提供的方法findAll("modelName"),我想從中你也應該明白了Ember Data是何等重要了吧
看到這里不知道讀者是否已經明白適配器和后端服務的關聯關系?如果有疑問請給我留言。
文中所說的后端就是我的node程序(放在server目錄下),前端就是我的Ember.js項目。
下面就是再結合數據庫。
加入數據庫其實到這步加不加數據庫已經不那么重要了!重要把服務端返回的數據改成從數據庫讀取就完了。我就簡單講解了。
連接MySQL連接MySQL的工作交給前面已經安裝好的node-mysql,如果還沒安裝請執行命令npm install mysqljs/mysql進行安裝。繼續修改后端服務代碼server/index.js。
module.exports = function(app) { // 與之前的內容不變 // // 引入MySQL模塊 var mysql = require("mysql"); // 獲取連接對象 var conn = mysql.createConnection({ host: "localhost", user: "root", password: "", // 開啟debug,可以在啟動ember項目的終端看到更多詳細的信息 database: "test" }); // 處理請求 http://localhost:4200/user app.get("/api/v1/users", function(req, res) { var jsonArr = new Array(); // 打開數據庫連接 conn.connect(); //查詢數據 conn.query("select * from user", function(err, rows, fields) { if (err) throw err; //遍歷返回的數據并設置到返回的json對象中 for (var i = 0; i < rows.length; i++) { jsonArr.push({ id: rows[i].id, username: rows[i].username, email: rows[i].email }); } // 返回前端 res.status(200).send({ users: jsonArr }); }); // 關閉數據庫連接 conn.end(); }); };
相比之前的代碼只是引入了mysql,增加連接對象聲明,然后在請求處理方法里查詢數據,默認在數據庫初始化了3條數據,如下截圖,另外 為了簡單起見我仍然使用的是RESTAdapter適配器,這樣處理也相對簡單。 獲取連接對象的代碼應該不用過多解釋了,就是填寫你本地連接數據庫的對應配置信息就行了。
記得修改適配器為RESTAdapter。
重啟項目。進入路由users可以看到數據庫的數據正確顯示出來了。
CRUD操作對于CRUD操作都舉一個例子,由于前面已經介紹過findAll查詢就不在此介紹CRUD中的R了。下面就對另外三個做一個例子:
更多有關數據的操作請看Ember.js 入門指南——新建、更新、刪除記錄。
為了方便演示再增加幾個路由和模板。
ember g template users/index ember g route users/new ember g route users/edit
上述3個命令創建了三個users的子路由和子模板。
新增、更新由于項目使用的是Ember Data,增加數據也是很簡單的,直接調用createRecord()創建一個record之后再調用save()方法保存到服務器。
另外新增和更新的處理方式相似,就直接寫在一個方法內。
// app/components/user-form.js // 新增,修改user import Ember from "ember"; export default Ember.Component.extend({ tipInfo: null, actions: { saveOrUpdate(id, user) { if (id) { //更新 let username = this.get("model.username"); let email = this.get("model.email"); if (username && email) { this.store.findRecord("user", id).then((u) => { u.set("username", username); u.set("email", email); u.save().then(() => { this.set("tipInfo", "更新成功"); // this.set("model.username", ""); // this.set("model.email", ""); }); }); } else { this.set("tipInfo", "請輸入username和email!"); } } else { //新增 let username = this.get("model.username"); let email = this.get("model.email"); if (username && email) { this.get("store").createRecord("user", { username: username, email: email }).save().then(() => { this.set("tipInfo", "保存成功"); this.set("model.username", ""); this.set("model.email", ""); }, (err) => { this.set("tipInfo", "保存失敗"+err); }); } else { this.set("tipInfo", "請輸入username和email!"); } } } } });
新增和修改處理是相似的,根據id是否為空判斷是否是新增還是更新。
hbs:user-form.hbs{{! 新增、修改都用到的表單,提出為公共部分}}{{title}}
{{#if tipInfo}}{{#link-to "users" class="btn btn-primary"}}返回{{/link-to}}
{{tipInfo}}{{/if}}
// app/routes/users/edit.js import Ember from "ember"; export default Ember.Route.extend({ // 根據id獲取某個記錄 model(params) { return this.store.findRecord("user", params.user_id); } });
點擊“編輯”的時候需要根據被點擊記錄的id查詢數據詳情,并返回到編輯頁面。
{{! 增加數據的表單}} {{user-form title="新增user" store=store model=model}}
{{! 修改數據的表單}} {{user-form title="修改user" store=store model=model}}
提取新增和修改這兩個模板的相同代碼為一個組件,兩個模板都調用組件。
后端處理代碼與前端對應的要有相應的后端處理服務,增加2個路由監聽,一個是監聽post提交(新增),一個是put提交(更新)。
// 處理請求 POST http://localhost:4200/users app.post("/api/v1/users", function(req, res) { var username = req.body.user.username; console.log("req.body.user.username = " + username); var email = req.body.user.email; console.log("req.body.user.email = " + email); // 打開數據庫連接 pool.getConnection(function(err, conn) { var queryParams = { username: username, email: email }; var query = conn.query("insert into user SET ?", queryParams, function(err, result) { if (err) throw err; console.log("result = " + result); // 返回前端 if (result) { res.status(200).send({ users: { id: result.insertId, username: username, email: email } }); } else { //沒有數據返回一個空的 // 返回前端 res.status(200).send({ users: { id: "", username: "", email: "" } }); } }); console.log("sql: " + query.sql); conn.release(); //釋放連接,放回到連接池 }); }); // 處理請求 POST http://localhost:4200/users/id 根據id更新某個數據 app.put("/api/v1/users/:id", function(req, res) { console.log("更新 POST /api/v1/users/:id"); console.log("req.params.id = " + req.params.id); console.log("req.body.user.username = " + req.body.user.username); var jsonArr = new Array(); // 打開數據庫連接 pool.getConnection(function(err, conn) { // 參數的次序要與SQL語句的參數次序一致 var queryParams = [ req.body.user.username, req.body.user.email, req.params.id ]; var query = conn.query("UPDATE user SET username = ?, email = ? where id = ?", queryParams, function(err, results, fields) { if (err) { console.log("更新出錯:"+err); throw err; } //遍歷返回的數據并設置到返回的json對象中,通常情況下只有一個數據,直接取第一個數據返回 if (results && results.length > 0) { jsonArr.push({ id: results[0].id, username: results[0].username, email: results[0].email }); // 返回前端 res.status(200).send({ users: jsonArr }); } // else { //沒有數據返回一個空的 // // 返回前端 // res.status(200).send({ // users: { // id: "", // username: "", // email: "" // } // }); // } console.log("SQL: " + query.sql); }); conn.release(); //釋放連接,放回到連接池 }); });
為何新增對應的是post方法,更新對應的是put方法,請看the rest adapter的詳細介紹(主要是第一個表格的內容)。
簡單測試點擊右上角的新增按鈕進入新增界面。
進入新增界面后輸入相應信息(我就不做數據的格式校驗了,有需要自己校驗數據格式)。然后點擊“保存”,保存成功會有提示信息。
點擊右上角的“返回”回到主列表頁面,查看新增的數據是否保存成功。
可以看到剛剛新增的數據已經顯示在列表上,為了進一步驗證數據已經保存成功,直接查看數據庫。
可以看到數據庫也已經成功保存了剛剛新增的數據。
修改的測試方式我就不啰嗦了,點擊列表上的修改按鈕進入修改頁面,修改后保存既可以,請自行測試。
刪除刪除處理相比新增更加簡單,直接發送一個delete請求即可。
Ember前端處理// app/routes/user.js import Ember from "ember"; export default Ember.Route.extend({ model() { return this.store.findAll("user"); }, actions: { // 刪除記錄 del(id) { console.log("刪除記錄:" + id); this.get("store").findRecord("user", id).then((u) => { u.destroyRecord(); // => DELETE to /users/2 }); } } });
用戶列表
{{#link-to "users.new" class="btn btn-primary"}}新增{{/link-to}}
# | 用戶名 | 郵箱 | 操作 |
---|---|---|---|
{{user.id}} | {{user.username}} | {{user.email}} | {{#link-to "users.edit" user.id}}修改{{/link-to}} | 刪除 |
這段代碼的與前面的代碼基本一致,就是增加了刪除。
后端處理在后端增加一個監聽刪除的路由。
// 處理請求 DELETE http://localhost:4200/users/id 刪除記錄 app.delete("/api/v1/users/:id", function(req, res) { var jsonArr = new Array(); var id = req.params.id; console.log("刪除 req.params.id = " + id); // 打開數據庫連接 pool.getConnection(function(err, conn) { var queryParams = [ id ]; var query = conn.query("delete from user where id = ?", queryParams, function(err, result) { if (err) throw err; // 返回前端 res.status(200).send({}); }); console.log("sql: " + query.sql); conn.release(); //釋放連接,放回到連接池 }); });測試刪除
測試刪除很簡單,直接在列表上點擊“刪除”按鈕即可刪除一條記錄。界面和數據庫的截圖我就不貼出來了,自己動手測試就知道了!!
數據可以正確刪除,但是,刪除之后控制臺會報如下錯誤:
找了官網文檔the rest adapter delete record按照官網的文檔處理仍然報錯!目前還沒找到好的處理方法,不知道是哪里出了問題,如果讀者知道請告訴我,謝謝。
到此CRUD操作也完成了,不足的就是在處理刪除的時候還是有點問題,目前還沒找到覺得辦法!但是總的來說對于CRUD的操作都是這么處理的,調用的方法也都是上述代碼所使用的方法。
未完待續……還差分頁沒完成。
總結文章寫到這里已經把我所想的內容介紹完畢了,不知道讀者是否看明白了。其中主要理解的知識點是:
Ember Data和adapter、record、model的關系
如何自定義適配器
如何根據Ember前端請求編寫后端處理
CRUD操作
分頁處理(目前還沒整合進來)
明白了上述幾點,本文的目的也達到了!如何有疑問歡迎給我留言,也期待著讀者能給我解答刪除報錯的問題!
文章源碼如果有需要歡迎star或者fork學習。下面是源碼地址:
https://github.com/ubuntuvim/emberData-adapter-database,歡迎follow我,一起學習交流!我在全球最大的同性交友網站等你哦!!
參考網址ember.js
ember-cli
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/91636.html
摘要:由于能力有限本示例不會完全自定義適配器和序列化器,示例仍然是使用官方推薦方式,重寫或者擴展以實現自定適配器和序列化器。在序列化器中調用響應請求的方法格式化返回的數據。上述就是的一個簡單實用示例。 文章來源:http://xcoding.tech/tags/Emberjs歡迎訪問源網站Ember Teach,Ember Teach致力于為您提供最權威、最前沿的Ember技術教程。。 ad...
摘要:就沒必要動牛刀,創建一個數據庫了執行完后,在目錄下創建一個程序,自動植入到當前項目中,訪問的和與訪問域名端口一致。就沒必要動牛刀,創建一個數據庫了本篇博文將為你介紹如何使用實現權限控制,我會創建一個簡單的登錄示例加以說明。 文章來源:http://blog.ddlisting.com 官網對于登錄、用戶權限的介紹只有一段簡單的說明,并沒有詳細說明如何使用service實現權限控制。下面...
摘要:在文件夾內創建,內容如下創建,內容如下使用安裝依賴在的頭部加入調用命令,同時在你的默認瀏覽器中打開。最后,我們更新下,給每個報道添加鏈接修改完畢地后,可以在瀏覽器中直接看到結果。 編者注:我們發現了有趣的系列文章《30天學習30種新技術》,正在翻譯,一天一篇更新,年終禮包。下面是第19天的內容。 到目前為止,我們這一系列文章涉及了Bower、AngularJS、GruntJS、P...
摘要:創建模型并設置關聯關聯關系設置模型關系一個對應多個,一個對應多個。手動在中增加關聯關系。并且是實現了數據表之間的關聯關系,比如一個對應多個,如下圖。 文章來源:模型高級特性,引入模型關聯關系 接著前面五篇: 環境搭建以及使用Ember.js創建第一個靜態頁面 引入計算屬性、action、動態內容 模型,保存數據到數據庫 發布項目,加入CRUD功能 從服務器獲取數據,引入組件 前言 ...
摘要:文章來源模型,保存數據到數據庫環境搭建以及使用創建第一個靜態頁面引入計算屬性動態內容繼續為讀者介紹如何使用構建一個完整的復雜的項目。 文章來源:模型,保存數據到數據庫 環境搭建以及使用Ember.js創建第一個靜態頁面 引入計算屬性、action、動態內容 繼續為讀者介紹如何使用Ember構建一個完整的、復雜的項目。 第一個Ember.js模型 在前面兩篇中實現了如何獲取界面輸入的...
閱讀 2212·2021-11-22 13:52
閱讀 3846·2021-11-10 11:36
閱讀 1380·2021-09-24 09:47
閱讀 1088·2019-08-29 13:54
閱讀 3360·2019-08-29 13:46
閱讀 1942·2019-08-29 12:16
閱讀 2108·2019-08-26 13:26
閱讀 3471·2019-08-23 17:10