--- title: '2019/12/28 VueJS 教學筆記: 用 JSON-SERVER 來模擬 AXIOS RESTFUL API 修改資料' disqus: hackmd --- 2019/12/28 VueJS 教學筆記: 用 JSON-SERVER 來模擬 AXIOS RESTFUL API 修改資料 === 綱要 [TOC] 複習第一天上過的AXIOS API環境建立 --- 如果你已經忘記了怎麼使用AXIOS的GET、POST、DELETE行為可以回到 [2019/09/07 VueJS 教學筆記: 生命週期與AXIOS API](https://hackmd.io/@FortesHuang/SycpsQ08B) 看看基本的AXIOS封裝方法。 這次上課我們要增加一個PUT的行為來做編輯指定資料的模擬功能。 增加PUT的行為 --- AXIOS內我們先來設定一個PUT行為封裝: **api.js** ```javascript= import axios from 'axios' const api = { headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, // get // ... // post // ... put: (url, params) => { return new Promise((resolve, reject) => { axios.put(url, params) .then((response) => { resolve(response.data) }) .catch((error) => { reject(error) }) }) }, // delete // ... }ㄏ export default api ``` 接著回到以前做過的`ApiTemp.vue` 然後用另一個cmd視窗啟動JSON-Server: `json-server --watch db.json` **ApiTemp.vue** ![](https://i.imgur.com/V2jb3tI.png) ```htmlmixed= <template> <div class="row column"> <!--新增一個新的表單--> <el-form label-width="8rem" data-width="20rem" data-space="space-vertical"> <el-form-item label="ID"> <el-input v-model="postObj.id" type="text" /> </el-form-item> <el-form-item label="Name"> <el-input v-model="postObj.name" type="text" /> </el-form-item> <el-form-item label="Class"> <el-input v-model="postObj.class" type="text" /> </el-form-item> <el-form-item label="Date"> <el-date-picker v-model="postObj.date" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" :placeholder="$t('select_datetime')" /> </el-form-item> <div class="row horizontal v_center end"> <el-button @click="packagePostData">Add Data(POST)</el-button> </div> </el-form> <!-- 沿用先前的el-table --> <el-table :data="tableData" style="width: 100%; overflow: hidden;" height="50vh"> <el-table-column prop="id" label="ID" align="center" width="100" /> <el-table-column prop="name" label="Name" align="center" width="100" /> <el-table-column prop="class" label="Class" /> <el-table-column prop="date" label="Date" /> <el-table-column label="Action" align="center"> <template slot-scope="scope"> <el-button type="danger" @click="delCheck(scope.row.id)">DELETE</el-button> <!--增加一個EDIT用的Button,綁定個openEditDialog的事件,並給予這行table資料中的物件作為參數--> <el-button type="warning" @click="openEditDialog(scope.row)">EDIT</el-button> </template> </el-table-column> </el-table> <!--編輯內容使用的Dialog--> <el-dialog title="編輯" :visible.sync="editDialog"> <el-form label-width="8rem" data-width="20rem" data-space="space-vertical"> <el-form-item label="ID"> <el-input v-model="editForm.id" type="text" /> </el-form-item> <el-form-item label="Name"> <el-input v-model="editForm.name" type="text" /> </el-form-item> <el-form-item label="Class"> <el-input v-model="editForm.class" type="text" /> </el-form-item> <el-form-item label="Date"> <el-date-picker v-model="editForm.date" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" :placeholder="$t('select_datetime')" /> </el-form-item> </el-form> <span slot="footer" class="dialog-footer"> <el-button @click="editDialog = false">取消</el-button> <el-button @click="updateData" type="primary">送出</el-button> </span> </el-dialog> </el-dialog> </div> </template> ``` ```javascript= import { getLanguage, setLanguage } from "../../lang" import { stringify } from 'querystring' export default { name: "apiTemp", data() { return { lang: 'zh_tw', tableData: [], postObj: { id: '', name: '', class: '', date: '' }, editForm: {}, editDialog: false, } }, created() { getLanguage this.packageGetData() }, methods: { async packageGetData() { // 需要修改一下source url,使GET Data後,先在JSON Server中自動排序一次 const url = 'http://localhost:3000/tableData?_sort=id' let res = await this.$api.get(url) console.log(res) this.tableData = [...res] // 正式環境才有後端給來的result回應,這裡只做註解 // if (res.result == 1) { // console.log(res) // this.tableData = [...res.data] // } else { // console.log('API error') // } }, async packagePostData() { const source = 'http://localhost:3000/tableData' const currentDate = new Date().toJSON().slice(0, 10) await this.$api.post(source, this.postObj) this.packageGetData() console.log(source.data) }, // 防止刪除按鈕誤觸,加上確認刪除提醒和成功與失敗時的提示 async delCheck(id) { try { await this.$confirm( '將會刪除資料,是否繼續?', '刪除資料', { confirmButtonText: '確認刪除', cancelButtonText: '取消', type: 'warning' }) await this.delData(id) this.$message({ message: '刪除成功', type: 'success' }) } catch { this.$message({ message: '已取消删除', type: 'info' }) } }, async delData(id) { const source = 'http://localhost:3000/tableData/' + `${id}` await this.$api.delete(source) this.packageGetData() console.log(this.tableData) }, /* 加入編輯資料的事件 */ /* 一開始必須先建置一個打開對話彈出視窗Dialog的事件,之後再由Dialog中的確認Button 去觸發PUT做Update資料 */ openEditDialog(obj) { this.editDialog = true // 改變editDialog的狀態打開Dialog // 直接將el-table該處scope.row的參數物件繼承給editForm,這樣打開視窗時裡面就會有對應資料內容顯示出來 this.editForm = {...obj} console.log('edit obj: ', this.editForm) }, async updateData() { let id = this.editForm.id // 指定修改對象的id const source = 'http://localhost:3000/tableData/' + `${id}` /* * async/await中可以使用 try/catch 來讓內置的Promise()出現問題時 * 可以在catch中指定的事件反應出來,反之在try當中就是成功操作資料修改 */ try { await this.$api.put(source, this.editForm) this.$message({ message: '編輯成功', type: 'success' }) this.editDialog = false console.log('ID ' + id + ' 編輯成功') } catch { this.$message.error('編輯失敗') } this.packageGetData() } } } ``` 現在我們可以試試看編輯其中一筆資料看看結果會如何: ![](https://i.imgur.com/9pbonoT.png) PUT與PATCH的不同 --- PUT真正意義上的動作應該是 Replace (Create or Update),也就是替換特定位置(ex: tableData/1)的資料,假如位置中沒有這筆資料,就Create新增進去。 但如果我們只需要更改一個屬性,卻得將整筆資料貼入,看起來實在有點佔用頻寬。 因此後來就有了PATCH這個方法讓我們可以只針對單一屬性做變更。 比如原本該筆資料POST新增後的物件內容是這樣: ```javascript= { "id": "001", "name": "Claire", "class": "Survivor", "date": "2019-12-26 00:00:00" } ``` 以PATCH的方式更新資料某個屬性就可以這樣做: **api.js** ```javascript= const api = { // ... // 封裝一個Patch的Promise() patch: (url, params) => { return new Promise((resolve, reject) => { axios.patch(url, params) .then((response) => { resolve(response.data) }) .catch((error) => { reject(error) }) }) }, } ``` **ApiTemp.vue** ```javascript= async patchData() { let id = this.editForm.id const source = 'http://localhost:3000/tableData/' + `${id}` try { await this.$api.patch(source, { name: 'Hunk' }) // 直接替換name後送出 } catch { this.$message.error('編輯失敗') } this.packageGetData() } ``` 可是話說回來,UI設計原本就是整張表單皆需要填寫資料才做Submit,中間又有表單驗證需要處理,所以通常正式環境只會使用POST來做所有的資料操作依據,包含新增、修改、刪除、搜尋。 漸漸的,PATCH就這麼地被遺忘了...XD ###### tags: `VueJS` `AXIOS` `JSON-Server`