---
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`