1、封裝
在js文件中封裝,
常用的有
import { get as getToken } from './token' //這個是簡化日常使用的path請求路徑,比如說完整的路徑是http://localhost:8080/api/aaa/bbb/ccc/,日常使用只需要/aaa/bbb/ccc/就可以了,VUE_APP_BASE_API根據自己需要配置 export const backend = (u) => `${process.env.VUE_APP_BASE_API}${u}` //設置請求頭和token export const options = (method) => { return { credentials: 'include', headers: { 'Authorization': `Bearer ${getToken()}`, 'Content-Type': 'application/json; charset=utf-8' }, method } } export const get = (path) => fetch(backend(path), options('GET')).then((res) => res.status === 200 ? res.json() : res.json().then(err => { throw err })) export const delete_ = (path) => fetch(backend(path), options('DELETE')).then((res) => res.status === 200 ? res.json() : res.json().then(err => { throw err })) export const post = (path, body) => { const data = options('POST') data.body = JSON.stringify(body) return fetch(backend(path), data).then((res) => res.status === 200 ? res.json() : res.json().then(err => { throw err })) } export const patch = (path, body) => { const data = options('PATCH') data.body = JSON.stringify(body) return fetch(backend(path), data).then((res) => res.status === 200 ? res.json() : res.json().then(err => { throw err })) } export const put = (path, body) => { const data = options('PUT') data.body = JSON.stringify(body) return fetch(backend(path), data).then((res) => res.status === 200 ? res.json() : res.json().then(err => { throw err })) }
2、使用
- 一般而言post/put/patch/delete都不需要url傳query,如需傳參數,可以通過path、body來傳參數,在path里面拼參數不會有url注入,因為有匹配;
比如:
import {delete_ as httpDelete} from "@/xxxxx/request";
...
httpDelete(`/iron/cfwz/${this.selectllist[0].id}`)
.then(() => {
this.$message.success("操作成功");
this.items = this.items.filter(
(x) => x.id !== this.selectllist[0].id
);
this.onCurrentChange(1, this.ztId);
})
.catch((e) => this.$message.error(e.message));
參數多的時候,可以把參數放在body里面;delete方法條件多時,可用post方法來處理。
- 只有get才需要傳query
(1)對於不需要傳參數到后端的,可使用request.js的get方式
import {get as httpGet} from "@/xxxxx/request";
...
httpGet(`/aaa/bbb/ccc/`)
.then((rst) => {
this.cjbms = rst;
})
.catch((e) => this.$message.error(e.message));
(2)對於參數少的,可以在path放參數
import {get as httpGet} from "@/xxxxx/request";
...
httpGet(`/aaa/bbb/ccc/${this.id}/`)
.then((rst) => {
this.obj = rst;
})
.catch((e) => this.$message.error(e.message));
(3)如果需要傳query,即在路徑后端拼接參數比如https://www.example.dev/?city=Rome&price=200,最好不要直接拼接到鏈接,要不然會有url注入。最好像下面這樣

為此,get請求再封裝一個
export const backend_url = (p) => new URL(`${process.env.VUE_APP_BASE_API}${p}`, window.location.href) export const get_by_url = (u) => fetch(u, options('GET')).then((res) => res.status === 200 ? res.json() : res.json().then(err => { throw err }))
使用
import {backend_url,get_by_url} from "@/xxxxx/request";
...
const u = backend_url("/aaa/bbb/ccc/");
u.searchParams.append("ztId", this.ztId);
get_by_url(u)
.then((rst) => {
this.cjbms = rst;
})
.catch((e) => this.$message.error(e.message));
3、不同傳參方式,后端接收注解不一樣
(1)path中傳參數
`/aaa/bbb/ccc/${this.id}`
@DeleteMapping("/aaa/bbb/ccc/{id}")
public Ok destroy(@Valid @PathVariable("id") int id) {
dwhzfaService.delete(id);
return new Ok();
}
(2)path后端拼接參數
`/aaa/bbb/ccc/?code=${this.code}`
@GetMapping("/aaa/bbb/ccc")
public int checkCode(@RequestParam(value = "code") String code) {
return dwhzfaRepository.countByCode(code);
}
(3)body傳參
httpPost(`/aaa/bbb/`, {
ztId: this.form.ztId,
year: this.form.yearAndMonth.getFullYear(),
month: this.form.yearAndMonth.getMonth() + 1,
})
.then(() => {
this.$message.success("操作成功");
this.$router.push({
name: "xxx.xx.x.index",
params: { ztId: this.form.ztId},
});
})
.catch((e) => this.$message.error(e.message));
})
.catch(() => {});
后端
@PostMapping("/")
public Ok create(@Valid @RequestBody CreateDwhzfa form) {
//CreateDwhzfa 是一個類,包含簽到body傳來的想要接收的屬性字段
dwhzfaService.add(form);
return new Ok();
}
4、上傳、下載
export const upload = () => { return { 'Authorization': `Bearer ${getToken()}` } } export const download = (path, name) => { const data = options('GET') fetch(backend(path), data) .then(response => response.blob()) .then(blob => { var url = window.URL.createObjectURL(blob) var a = document.createElement('a') a.href = url a.download = name document.body.appendChild(a) // for firefox a.click() a.remove() }) }
import { upload as uploadHeaders, download as httpDownload } from "@/xxxx/request"; computed: { uploadHeaders, }, methods: { exportExcel() { httpDownload( `/xxx/xx/exportExcel/?year=${parseInt(this.year)}&ztId=11`, "導出模板.xls" ); },
successUploadFile() {
this.$message.success("導入成功");
this.excelFileList = [];
},
}
<el-upload style="float: left; margin-left: 10px" class="upload-demo" action="/api/xxx/xx/upload" :data="{}" :headers="uploadHeaders" :limit="1" :file-list="excelFileList" :on-success="successUploadFile" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" > <el-button size="small" type="primary">導入</el-button> </el-upload>
data(){ return{ excelFileList: [], } }
