[微精通:網頁設計Vue + Node.js + MySQL] 4.2.CRUD

資料的操作不外乎四個動作 - CRUD,即新增Create、查詢Read、修改Update與刪除Delete。

 

image/svg+xml4.2.CRUD var express = require( 'express' ); var api = express(); var zombies = [ {id: 1 , name: ' 瘋狂傑克 ' , age: 3.3 , isVegetarian: true , typeImgSrc: "z1.png" }, {id: 2 , name: ' 懶懶瑪琍 ' , age: 10 , isVegetarian: true , typeImgSrc: "z2.png" }, {id: 3 , name: ' ⼤提姆 ' , age: 5 , isVegetarian: false , typeImgSrc: "z3.png" }, {id: 4 , name: ' 史提夫 ' , age: 2 , isVegetarian: false , typeImgSrc: "z4.png" }, {id: 5 , name: ' 功夫李 ' , age: 1 , isVegetarian: true , typeImgSrc: "z5.png" } ] ; api. post ( '/api/ getZombies ' , function (req, res) { var result = { data : null , error : null } ; result . data = zombies ; res.send ( JSON.stringify ( result )); } ); api.listen( 80 , function () { console.log( 'Zombie api listening on port 80!' ); }); var express = require( 'express' ); var api = express(); var zombies = [ {id: 1 , name: ' 瘋狂傑克 ' , age: 3.3 , isVegetarian: true , typeImgSrc: "z1.png" }, {id: 2 , name: ' 懶懶瑪琍 ' , age: 10 , isVegetarian: true , typeImgSrc: "z2.png" }, {id: 3 , name: ' ⼤提姆 ' , age: 5 , isVegetarian: false , typeImgSrc: "z3.png" }, {id: 4 , name: ' 史提夫 ' , age: 2 , isVegetarian: false , typeImgSrc: "z4.png" }, { id : 5 , name: ' 功夫李 ' , age: 1 , isVegetarian: true , typeImgSrc: "z5.png" } ] ; var maxID = 5 ; // 略過⼀些程式 api. post ( '/api/ addZombie ' , express.text() , function (req, res) { var result = { data: null , error: null } ; try { let zombie = JSON.parse ( req . body ); if ( typeof zombie.name != 'string' || zombie.name.trim() == "" ) { result . error = " 請輸入名字且必須為字串。 " ; res.send ( JSON.stringify ( result )); return ; } if ( typeof zombie.age != 'number' ){ result.error = " 請輸入變異年份且必須為數值。 " ; res.send(JSON.stringify(result)); return ; } if ( typeof zombie.isVegetarian != 'boolean' ){ result.error = " 請輸入是否為素食者且必須為布林值。 " ; res.send(JSON.stringify(result)); return ; } if ( typeof zombie.typeImgSrc != 'string' || [ 'z1.png' , 'z2.png' , 'z3.png' , 'z4.png' , 'z5.png' ].indexOf(zombie.typeImgSrc) == - 1 ){ result.error = " 請輸入類型圖片,且值必須為 z1.png z2.png z3.png z4.png z5.png " ; res.send(JSON.stringify(result)); return ; } maxID = maxID + 1 ; let newID = maxID ; let newZombie = { id: newID, name: zombie.name, age: zombie.age, isVegetarian: zombie.isVegetarian, typeImgSrc: zombie.typeImgSrc } ; zombies.push ( newZombie ); result.data = newZombie ; res.send( JSON.stringify ( result )); } catch (e) { result.error = e.toString(); res.send(JSON.stringify(result)); } } ); api.listen( 80 , function () { console.log( 'Zombie api listening on port 80!' ); }); var express = require( 'express' ); var api = express(); var zombies = [ {id: 1 , name: ' 瘋狂傑克 ' , age: 3.3 , isVegetarian: true , typeImgSrc: "z1.png" }, {id: 2 , name: ' 懶懶瑪琍 ' , age: 10 , isVegetarian: true , typeImgSrc: "z2.png" }, {id: 3 , name: ' ⼤提姆 ' , age: 5 , isVegetarian: false , typeImgSrc: "z3.png" }, {id: 4 , name: ' 史提夫 ' , age: 2 , isVegetarian: false , typeImgSrc: "z4.png" }, { id : 5 , name: ' 功夫李 ' , age: 1 , isVegetarian: true , typeImgSrc: "z5.png" } ] ; var maxID = 5 ; // 略過⼀些程式 api. post ( '/api/ updateZombie ' , express.text(), function (req, res) { var result = { data: null , error: null }; try { let zombie = JSON.parse ( req.body ); if ( typeof zombie.id != 'number' || zombies.map (x => x. id ). indexOf (zombie.id) == - 1 ){ result.error = " 請輸入有效的 id " ; res.send(JSON.stringify(result)); return ; } if ( typeof zombie.name != 'string' || zombie.name.trim() == "" ){ result.error = " 請輸入名字且必須為字串。 " ; res.send(JSON.stringify(result)); return ; } if ( typeof zombie.age != 'number' ){ result.error = " 請輸入變異年份且必須為數值。 " ; res.send(JSON.stringify(result)); return ; } if ( typeof zombie.isVegetarian != 'boolean' ){ result.error = " 請輸入是否為素食者且必須為布林值。 " ; res.send(JSON.stringify(result)); return ; } if ( typeof zombie.typeImgSrc != 'string' || [ 'z1.png' , 'z2.png' , 'z3.png' , 'z4.png' , 'z5.png' ].indexOf(zombie.typeImgSrc) == - 1 ){ result.error = " 請輸入類型圖片,且值必須為 z1.png z2.png z3.png z4.png z5.png " ; res.send(JSON.stringify(result)); return ; } let index = zombies.map(x => x.id). indexOf ( zombie.id ); zombies [ index ]. name = zombie.name ; zombies [ index ]. age = zombie.age ; zombies [ index ]. isVegetarian = zombie.isVegetarian ; zombies [ index ]. typeImgSrc = zombie.typeImgSrc ; result.data = zombies [ index ]; res.send( JSON.stringify ( result )); } catch (e){ result.error = e.toString(); res.send(JSON.stringify(result)); } }); api.listen( 80 , function () { console.log( 'Zombie api listening on port 80!' ); }); var express = require( 'express' ); var api = express(); var zombies = [ {id: 1 , name: ' 瘋狂傑克 ' , age: 3.3 , isVegetarian: true , typeImgSrc: "z1.png" }, {id: 2 , name: ' 懶懶瑪琍 ' , age: 10 , isVegetarian: true , typeImgSrc: "z2.png" }, {id: 3 , name: ' ⼤提姆 ' , age: 5 , isVegetarian: false , typeImgSrc: "z3.png" }, {id: 4 , name: ' 史提夫 ' , age: 2 , isVegetarian: false , typeImgSrc: "z4.png" }, { id : 5 , name: ' 功夫李 ' , age: 1 , isVegetarian: true , typeImgSrc: "z5.png" } ] ; var maxID = 5 ; // 略過⼀些程式 api. post ( '/api/ deleteZombie ' , express.text(), function (req, res) { var result = { data: null , error: null }; try { let zombie = JSON.parse ( req.body ); if ( typeof zombie.id != 'number' || zombies.map (x => x. id ). indexOf (zombie.id) == - 1 ){ result.error = " 請輸入有效的 id " ; res.send(JSON.stringify(result)); return ; } let index = zombies.map(x => x.id). indexOf(zombie.id) ; let deletedZombie = zombies [ index ]; zombies . splice ( index , 1 ); result.data = deletedZombie ; res.send( JSON.stringify ( result )); } catch (e){ result.error = e.toString(); res.send(JSON.stringify(result)); } }); api.listen( 80 , function () { console.log( 'Zombie api listening on port 80!' ); }); console.log( typeof 10.123 ); var num1 = parseFloat ( ' 10.123 ' ); console.log( typeof num1 ); var z1 = { id: 1 , name: ' 瘋狂傑克 ' , age: 3.3 , isVegetarian: true , typeImgSrc: “z1.png" } ; var str1 = JSON . stringify ( z1 ); console.log(str1); console.log( typeof str1 ); var str2 = ' {"id":1, "name":" 懶懶瑪琍 ", "age":10, "isVegetarian":true, "typeImgSrc": “z1.png"} ' ; var z2 = JSON.parse ( str2 ); console.log(z2); console.log( typeof z2 ); var names = [ ' 瘋狂傑克 ' , ' 懶懶瑪琍 ' , ' ⼤提姆 ' , ' 史提夫 ' , 功夫李 ' ] ; var hiNames = names . map ( x => 'hi~' + x ); console.log( hiNames ); 有了殭屍 API ,但基本上⼜要有哪些功能呢 ? 1. 我們現在有了殭屍 API ,最後也會有 80 port 上啟動提供 API 的服務,但接下來我們 應該為殭屍 API 增加哪些功能呢 ? 理解資料的 CRUD 1. 其中殭屍資料就像⼀組集合,⽽我們 通常對資料做的動作為外乎是 CRUD 2. C Create 新增 殭屍資料⾄集合中。 3. R Read 查詢集合 中的殭屍資料。 4. U Update 修改 集合中的殭屍資料。 6. D Delete 刪除 集合中的殭屍資料。 1. 建立殭屍的 CRUD API - R Read 查詢 w4_2_2 - server.js w4_2_1 - server.js 1. zombies 變數,裡⾯是放著⼀個陣 列,陣列中存放⽬前所有的殭屍物件,預 設為 5 個殭屍物件。 2. 統⼀使⽤ post() ⽅法,建立⼀個 API 徑,路徑取名為 ’getZombies’ ,表⽰我們要 建立⼀個取得所有殭屍物件的 API 3. 這是我們統⼀使⽤的資料結構,其中 data error 屬性,預設為 null 5. 接著對 data 放入所有的殭屍物件。 6. 使⽤ JSON 物件上的 stringify() 函式, result 變數中的物件轉為字串。 7. 再透過 res 參數取得 response 物件,呼叫 send() ⽅法將字串傳回給呼叫的⽤⼾。 4. 在此範例中,我們使⽤不到 error 屬性。 2. 建立殭屍的 CRUD API - C Create 建立 w4_2_3 - server.js 1. 注意,⽬前我們所有的殭屍物件都是透過陣列 保存的,陣列則存放在 zombies 變數中。 3. 使⽤ post() 建立⼀個 addZombie API ,⽤來加入⼀ 個新的殭屍物件,這個 API 也代表著 CRUD 中的 Create 立。這次在第 2 個參數中加上 express.text() 表⽰要以 純⽂字的⽅式接收上傳上來的殭屍資料。 5. 使⽤ try/catch ,若中間的程式有異常,則將異常 的訊息透過 error 屬性回傳回去,可能的錯誤很多,如以 JSON 格式解析⽤⼾上傳的資料失敗時也會發⽣異常。 4. 準備回傳的資料結構。 6. 透過 req 參數取得 request 物件,其中的 body 屬性存放著⽤⼾上傳的殭屍資訊。 7. 透過 JSON.parse() ⽅法將 JSON 字串解析為物件,並放在 zombie 變數中。 8. 檢查名字是否為字串 string ,且不為空字串。 typeof 關鍵字可 以取得 zombie.neme 中值的型別,在此檢查是否取得 ’string’ 型別,若回傳的為 'string' ,則在接著對 zombie.name 屬性呼叫 trim() 去除字串左右的空⽩,去除了檢查是否還是空⽩。 10. 最後使⽤ return 離開函式以中斷後續的執⾏。 9. 檢測不過,則設定 error 屬性為 " 請輸 入名字且必須為字串。 " ,在透過 res 中的 response 物件回傳這個錯誤的資訊。 11. 依序簡查變異年份 age 是否為 number 、是否為素食 isVegetarian 是否為 boolean ,若不過則同樣設定 error 屬性後回傳,並使⽤ return 離開。 12. 特別的是類型圖片 typeImgSrc 除了檢查是否為字串 外,也會透過 indexOf() 查看 typeImgSrc 中的值是否存在 'z1.png' 'z2.png' 'z3.png' 'z4.png' 'z5. png' 中,若不存在則會回傳 -1 2. 注意,在此我們宣告⼀個 maxID 變數,⽤來保 存⽬前最⼤的 id 值,⽽⽬前最⼤的值為 5 ,後續我 們將使⽤到它。 13. 將最⼤ id 值累加 1 ,並放在 newID 變數中,作為新的殭屍物件的編號。 14 建立⼀個新的殭屍物件,將資訊轉放入這個殭 屍物件,以避免加入使⽤者上傳的多餘資訊。 15. push() ⽅法加入⾄ zombies 變數 的陣列中,表⽰新增了這個殭屍物件。 16. 最後將這個新的殭屍物件放在 result data 屬性中回傳,它會多⼀個 id 值,是 api 幫忙加上的。 JavaScript 中, try/catch 就正⽤來補抓程式錯誤⽤的,當發⽣錯誤 時若使⽤ try/catch 則可處理這個錯誤,避免程式因錯誤⽽中斷的問題。 3. 建立殭屍的 CRUD API - U Update 更新 w4_2_4 - server.js 1. 再次提醒,⽬前我們所有的殭屍物件都是透過 陣列保存的,陣列則存放在 zombies 變數中。 2. 同樣透過 req 參數取得 request 物件,其 中的 body 屬性存放著⽤⼾上傳的殭屍資訊。 2. 建立 updateZombie api ,這個 api 與建立殭屍的 createZombie 類似。 3. 不同的是它會檢查是否有 id 屬性,且檢查是否存在於 zombies 變數中的陣列中。⾸ 先使⽤ map() ⽅法取得所有殭屍的 id 值的陣列,在透過 indexOf() ⽅法查看這個陣列中 是否有上傳的殭屍物件的 id 值,若無,則設定 error 回傳錯誤訊息。 4. addZombie 相同的名字 name 、變異年份 age 、是否為素食者 isVegerarian 與類型圖片 typeImgSrc 的檢查。 5. 透過 map() ⽅法取得所有殭屍物件 id 值的陣列,在以 id 找出這個殭屍所在的索引位置,並存於 index 變數中。 6. 使⽤ index 變數中的索引值指向這個殭屍物件,之後依 序更新 name age isVegetarian typeImgSrc 7. 最後放在 result 中的 data 屬性中,回傳這個更新後的殭屍物件。 4. 建立殭屍的 CRUD API - D Delete 刪除 w4_2_5 - server.js 1. 再次提醒,⽬前我們所有的殭屍物件都是透過 陣列保存的,陣列則存放在 zombies 變數中。 2. 建立 deleteZombie api ,⽤來刪除殭屍物件。 3. 同樣透過 req 參數取得 request 物件,其中 body 屬性存放著⽤⼾上傳的殭屍的 id 資訊。 4. updateZombie API 相同,檢查是否有 id 性,且檢查是否存在於 zombies 變數中的陣列中。 5. updateZombie API 相同,找出這個 id 有的索引位置並存放於 index 變數中。 6. 將這個殭屍物件透過索引取出後存放在 deletedZombie 變數中。 8. 回傳這個被刪除的殭屍物件。 7. 透過 splice() ⽅法,移除這個索引位置的殭屍物件。 5. node ,啟動 API 伺服器 w4_2_5 - server.js 1. w4_2_5 擁有完整的程式,在 Terminal 中輸入 node server.js 啟動 API 服務。 6. Postman ,測試殭屍 API w4_2_5 - server.js 1. POST ,輸入 http://127.0.0/api/ getZombies ,測試 CRUD R Read 讀取。 2. 按下 ’Send' 3. 查看回應 Reponse 中的內容 Body ,你會看到 回傳的所有殭屍物件在 data 屬性中。 4. 接下來測試 CRUD C Create 建立新的殭屍資料, url 網址為 addZombie ,同 樣選 POST 5. 我們將要傳送的資料寫在內容 Body 的部份,格式選 raw 原始格式。 接下來以 JSON 格式輸入⼀個名叫 隻佬 的殭屍,相關資料如畫⾯中的 內容,在此也必須注意⼤⼩寫。 6. 按下 ’Send' 傳送。 7. 成功後會回傳這個新建的殭屍物件在 data 屬性 中,它的 id 也是在新增 api 中加上的唯⼀識別值。 8. 這時在透過 ’getZombies’API 查看所有殭屍物 件,你會發現多了⼀個 id 6 的⼤隻佬殭屍物件。 9. 當然,我們開發的 API 都有驗證資料的程序,比如我們刻 意對新增殭屍的 addZombie API 傳送 ”age":"abc" 的資 料,這時就會出錯,回傳的 JSON error 屬性就會有說明, 說明到底發⽣了什麼錯。 10. 接來下呼叫 CRUD 中的 U Update 更新 API - updateZombie 來更 新殭屍的資料,在此我們更新 id 1 的殭屍資料,主要將名字 name 從改 瘋狂傑克 22' 11. 成功更新後會回傳更新後的資料,其名字 name 變為 ' 瘋理傑克 22' 12. 最後呼叫 CRUD D Delete API - deleteZombie ,在此只要傳 送要刪除的 id 編號即可,我們傳入 3 ,把 id 3 的殭屍物件刪除。 13. 刪除後會回傳這個被我們刪除得殭屍物件資料。 14. 再次透過 getZombies 查詢所有殭屍物件。 15. 你會發現 id 1 的殭屍物件,它的名字 name 是被我們呼叫更新 API - updateZombie API 時改動為 瘋狂傑克 22’ 的。其中 id 3 的殭屍物 件也不⾒了,也是先前透過呼叫刪除 API - deteleZombie 時刪除的。 JavaScript 函式詳解: parseFloat() JSON.stringify() Json.parse() map() w4_2_6 - server.js 1. ⾸先使⽤ typeof 這個關鍵字查看 ’10.123' 字串的型別, 會得到 string 字樣,表⽰這是⼀個字串。 2. 要將字串 string 轉為數值,可能你希望做⼀些加減乘除,這時可 使⽤ parseFloat() 函式將 string 字串轉為 number 數值的資料。 3. 這時 typeof 檢查型別,會是 number 數值, 這就是確定它已轉為數值類的資料了, 4. ⽤⼤括號 ({}) 建立⼀個物件放存 z1 變數中。 5. 為了要能透過 http 協定傳輸資料,這時我們會將 JavaScript 的物件轉為 string 字串好進⾏傳輸,這時就 可透過 JSON 類別上的 stringify() ⽅法進⾏轉換。 6. 使⽤ typeof 查看存在於 str1 變數中值, 你會發現它已被轉為 string 字串了。 7. 注意,這是使⽤單引號產⽣的 JSON 字串,它是⼀個字 串。其中的格式符合 JSON 的要求,以雙引號 (“”) 將屬性與 字串包起來。這字串存放在 str2 變數中。 8. 若要將 JSON 字串的轉為⼀個 JavaScript 的物件,則可 使⽤ JSON 類別上的 parse() ⽅法做轉換,在此將 str2 變數 中的 JSON 字串轉為 Javscript 的物件。 9. 使⽤ typeof 查看型別,會得到 object 物件的型別。 10. 這是⼀個陣列,存放了 5 個殭屍的名字,這個陣列存放在 names 變數中。 11. 陣列上的 map() ⽅法其實非常簡單,就是做 轉換, 5 個殭屍的姓名轉換成另 5 個不同的資料。 12. ⽽要做什麼轉換呢 ? 這個轉換則透過⼀個函式進⾏,在此 給的是箭頭函式, x 會依序接收每個陣列中的殭屍名字,⽽後 透過鍵頭 (=>) 右邊的運算式,為每個殭屍加上 ’hi~' 後回傳。 13. 最後還是會得到 5 個字串的陣列,只是皆被轉換為加上 ’hi~' 的殭屍姓名。 1 2 3 4 5 6 7 1 2 3 4 5 6 7

留言