談?wù)刅ue.js——vue-resource全攻略
概述
上一篇我們介紹了如何將$.ajax和Vue.js結(jié)合在一起使用,并實(shí)現(xiàn)了一個簡單的跨域CURD示例。Vue.js是數(shù)據(jù)驅(qū)動的,這使得我們并不需要直接操作DOM,如果我們不需要使用jQuery的DOM選擇器,就沒有必要引入jQuery。vue-resource是Vue.js的一款插件,它可以通過XMLHttpRequest或JSONP發(fā)起請求并處理響應(yīng)。也就是說,$.ajax能做的事情,vue-resource插件一樣也能做到,而且vue-resource的API更為簡潔。另外,vue-resource還提供了非常有用的inteceptor功能,使用inteceptor可以在請求前和請求后附加一些行為,比如使用inteceptor在ajax請求時顯示loading界面。
本文的主要內(nèi)容如下:
- 介紹vue-resource的特點(diǎn)
- 介紹vue-resource的基本使用方法
- 基于this.$http的增刪查改示例
- 基于this.$resource的增刪查改示例
- 基于inteceptor實(shí)現(xiàn)請求等待時的loading畫面
- 基于inteceptor實(shí)現(xiàn)請求錯誤時的提示畫面
本文11個示例的源碼:http://xiazai.jb51.net/201701/yuanma/vue-resource_jb51.rar
vue-resource特點(diǎn)
vue-resource插件具有以下特點(diǎn):
1. 體積小
vue-resource非常小巧,在壓縮以后只有大約12KB,服務(wù)端啟用gzip壓縮后只有4.5KB大小,這遠(yuǎn)比jQuery的體積要小得多。
2. 支持主流的瀏覽器
和Vue.js一樣,vue-resource除了不支持IE 9以下的瀏覽器,其他主流的瀏覽器都支持。
3. 支持Promise API和URI Templates
Promise是ES6的特性,Promise的中文含義為“先知”,Promise對象用于異步計算。
URI Templates表示URI模板,有些類似于ASP.NET MVC的路由模板。
4. 支持?jǐn)r截器
攔截器是全局的,攔截器可以在請求發(fā)送前和發(fā)送請求后做一些處理。
攔截器在一些場景下會非常有用,比如請求發(fā)送前在headers中設(shè)置access_token,或者在請求失敗時,提供共通的處理方式。
vue-resource使用
引入vue-resource
<script src="js/vue.js"></script> <script src="js/vue-resource.js"></script>
基本語法
引入vue-resource后,可以基于全局的Vue對象使用http,也可以基于某個Vue實(shí)例使用http。
// 基于全局Vue對象使用http Vue.http.get('/someUrl', [options]).then(successCallback, errorCallback); Vue.http.post('/someUrl', [body], [options]).then(successCallback, errorCallback); // 在一個Vue實(shí)例內(nèi)使用$http this.$http.get('/someUrl', [options]).then(successCallback, errorCallback); this.$http.post('/someUrl', [body], [options]).then(successCallback, errorCallback);
在發(fā)送請求后,使用then方法來處理響應(yīng)結(jié)果,then方法有兩個參數(shù),第一個參數(shù)是響應(yīng)成功時的回調(diào)函數(shù),第二個參數(shù)是響應(yīng)失敗時的回調(diào)函數(shù)。
then方法的回調(diào)函數(shù)也有兩種寫法,第一種是傳統(tǒng)的函數(shù)寫法,第二種是更為簡潔的ES 6的Lambda寫法:
// 傳統(tǒng)寫法 this.$http.get('/someUrl', [options]).then(function(response){ // 響應(yīng)成功回調(diào) }, function(response){ // 響應(yīng)錯誤回調(diào) }); // Lambda寫法 this.$http.get('/someUrl', [options]).then((response) => { // 響應(yīng)成功回調(diào) }, (response) => { // 響應(yīng)錯誤回調(diào) });
PS:做過.NET開發(fā)的人想必對Lambda寫法有一種熟悉的感覺。
支持的HTTP方法
vue-resource的請求API是按照REST風(fēng)格設(shè)計的,它提供了7種請求API:
- get(url, [options])
- head(url, [options])
- delete(url, [options])
- jsonp(url, [options])
- post(url, [body], [options])
- put(url, [body], [options])
- patch(url, [body], [options])
除了jsonp以外,另外6種的API名稱是標(biāo)準(zhǔn)的HTTP方法。當(dāng)服務(wù)端使用REST API時,客戶端的編碼風(fēng)格和服務(wù)端的編碼風(fēng)格近乎一致,這可以減少前端和后端開發(fā)人員的溝通成本。
客戶端請求方法 | 服務(wù)端處理方法 |
---|---|
this.$http.get(...) | Getxxx |
this.$http.post(...) | Postxxx |
this.$http.put(...) | Putxxx |
this.$http.delete(...) | Deletexxx |
options對象
發(fā)送請求時的options選項(xiàng)對象包含以下屬性:
參數(shù) | 類型 | 描述 |
---|---|---|
url | string |
請求的URL |
method | string |
請求的HTTP方法,例如:'GET', 'POST'或其他HTTP方法 |
body | Object , FormData string |
request body |
params | Object |
請求的URL參數(shù)對象 |
headers | Object |
request header |
timeout | number |
單位為毫秒的請求超時時間 (0 表示無超時時間) |
before | function(request) |
請求發(fā)送前的處理函數(shù),類似于jQuery的beforeSend函數(shù) |
progress | function(event) |
ProgressEvent回調(diào)處理函數(shù) |
credentials | boolean |
表示跨域請求時是否需要使用憑證 |
emulateHTTP | boolean |
發(fā)送PUT, PATCH, DELETE請求時以HTTP POST的方式發(fā)送,并設(shè)置請求頭的X-HTTP-Method-Override |
emulateJSON | boolean |
將request body以application/x-www-form-urlencoded content type發(fā)送 |
emulateHTTP的作用
如果Web服務(wù)器無法處理PUT, PATCH和DELETE這種REST風(fēng)格的請求,你可以啟用enulateHTTP現(xiàn)象。啟用該選項(xiàng)后,請求會以普通的POST方法發(fā)出,并且HTTP頭信息的X-HTTP-Method-Override屬性會設(shè)置為實(shí)際的HTTP方法。
Vue.http.options.emulateHTTP = true;
emulateJSON的作用
如果Web服務(wù)器無法處理編碼為application/json的請求,你可以啟用emulateJSON選項(xiàng)。啟用該選項(xiàng)后,請求會以application/x-www-form-urlencoded作為MIME type,就像普通的HTML表單一樣。
Vue.http.options.emulateJSON = true;
response對象
response對象包含以下屬性:
方法 | 類型 | 描述 |
---|---|---|
text() | string |
以string形式返回response body |
json() | Object |
以JSON對象形式返回response body |
blob() | Blob |
以二進(jìn)制形式返回response body |
屬性 | 類型 | 描述 |
ok | boolean |
響應(yīng)的HTTP狀態(tài)碼在200~299之間時,該屬性為true |
status | number |
響應(yīng)的HTTP狀態(tài)碼 |
statusText | string |
響應(yīng)的狀態(tài)文本 |
headers | Object |
響應(yīng)頭 |
注意:本文的vue-resource版本為v0.9.3,如果你使用的是v0.9.0以前的版本,response對象是沒有json(), blob(), text()這些方法的。
CURD示例
提示:以下示例仍然沿用上一篇的組件和WebAPI,組件的代碼和頁面HTML代碼我就不再貼出來了。
GET請求
var demo = new Vue({ el: '#app', data: { gridColumns: ['customerId', 'companyName', 'contactName', 'phone'], gridData: [], apiUrl: 'http://211.149.193.19:8080/api/customers' }, ready: function() { this.getCustomers() }, methods: { getCustomers: function() { this.$http.get(this.apiUrl) .then((response) => { this.$set('gridData', response.data) }) .catch(function(response) { console.log(response) }) } } })
這段程序的then方法只提供了successCallback,而省略了errorCallback。
catch方法用于捕捉程序的異常,catch方法和errorCallback是不同的,errorCallback只在響應(yīng)失敗時調(diào)用,而catch則是在整個請求到響應(yīng)過程中,只要程序出錯了就會被調(diào)用。
在then方法的回調(diào)函數(shù)內(nèi),你也可以直接使用this,this仍然是指向Vue實(shí)例的:
getCustomers: function() { this.$http.get(this.apiUrl) .then((response) => { this.$set('gridData', response.data) }) .catch(function(response) { console.log(response) }) }
為了減少作用域鏈的搜索,建議使用一個局部變量來接收this。
JSONP請求
getCustomers: function() { this.$http.jsonp(this.apiUrl).then(function(response){ this.$set('gridData', response.data) }) }
POST請求
var demo = new Vue({ el: '#app', data: { show: false, gridColumns: [{ name: 'customerId', isKey: true }, { name: 'companyName' }, { name: 'contactName' }, { name: 'phone' }], gridData: [], apiUrl: 'http://211.149.193.19:8080/api/customers', item: {} }, ready: function() { this.getCustomers() }, methods: { closeDialog: function() { this.show = false }, getCustomers: function() { var vm = this vm.$http.get(vm.apiUrl) .then((response) => { vm.$set('gridData', response.data) }) }, createCustomer: function() { var vm = this vm.$http.post(vm.apiUrl, vm.item) .then((response) => { vm.$set('item', {}) vm.getCustomers() }) this.show = false } } })
PUT請求
updateCustomer: function() { var vm = this vm.$http.put(this.apiUrl + '/' + vm.item.customerId, vm.item) .then((response) => { vm.getCustomers() }) }
Delete請求
deleteCustomer: function(customer){ var vm = this vm.$http.delete(this.apiUrl + '/' + customer.customerId) .then((response) => { vm.getCustomers() }) }
使用resource服務(wù)
vue-resource提供了另外一種方式訪問HTTP——resource服務(wù),resource服務(wù)包含以下幾種默認(rèn)的action:
get: {method: 'GET'}, save: {method: 'POST'}, query: {method: 'GET'}, update: {method: 'PUT'}, remove: {method: 'DELETE'}, delete: {method: 'DELETE'}
resource對象也有兩種訪問方式:
- 全局訪問:Vue.resource
- 實(shí)例訪問:this.$resource
resource可以結(jié)合URI Template一起使用,以下示例的apiUrl都設(shè)置為{/id}了:
apiUrl: 'http://211.149.193.19:8080/api/customers{/id}'
GET請求
使用get方法發(fā)送GET請求,下面這個請求沒有指定{/id}。
getCustomers: function() { var resource = this.$resource(this.apiUrl) vm = this resource.get() .then((response) => { vm.$set('gridData', response.data) }) .catch(function(response) { console.log(response) }) }
POST請求
使用save方法發(fā)送POST請求,下面這個請求沒有指定{/id}。
createCustomer: function() { var resource = this.$resource(this.apiUrl) vm = this resource.save(vm.apiUrl, vm.item) .then((response) => { vm.$set('item', {}) vm.getCustomers() }) this.show = false }
PUT請求
使用update方法發(fā)送PUT請求,下面這個請求指定了{(lán)/id}。
updateCustomer: function() { var resource = this.$resource(this.apiUrl) vm = this resource.update({ id: vm.item.customerId}, vm.item) .then((response) => { vm.getCustomers() }) }
{/id}相當(dāng)于一個占位符,當(dāng)傳入實(shí)際的參數(shù)時該占位符會被替換。
例如,{ id: vm.item.customerId}中的vm.item.customerId為12,那么發(fā)送的請求URL為:
http://211.149.193.19:8080/api/customers/12
DELETE請求
使用remove或delete方法發(fā)送DELETE請求,下面這個請求指定了{(lán)/id}。
deleteCustomer: function(customer){ var resource = this.$resource(this.apiUrl) vm = this resource.remove({ id: customer.customerId}) .then((response) => { vm.getCustomers() }) }
使用inteceptor
攔截器可以在請求發(fā)送前和發(fā)送請求后做一些處理。
基本用法
Vue.http.interceptors.push((request, next) => { // ... // 請求發(fā)送前的處理邏輯 // ... next((response) => { // ... // 請求發(fā)送后的處理邏輯 // ... // 根據(jù)請求的狀態(tài),response參數(shù)會返回給successCallback或errorCallback return response }) })
在response返回給successCallback或errorCallback之前,你可以修改response中的內(nèi)容,或做一些處理。
例如,響應(yīng)的狀態(tài)碼如果是404,你可以顯示友好的404界面。
如果不想使用Lambda函數(shù)寫法,可以用平民寫法:
Vue.http.interceptors.push(function(request, next) { // ... // 請求發(fā)送前的處理邏輯 // ... next(function(response) { // ... // 請求發(fā)送后的處理邏輯 // ... // 根據(jù)請求的狀態(tài),response參數(shù)會返回給successCallback或errorCallback return response }) })
示例1
之前的CURD示例有一處用戶體驗(yàn)不太好,用戶在使用一些功能的時候如果網(wǎng)絡(luò)較慢,畫面又沒有給出反饋,用戶是不知道他的操作是成功還是失敗的,他也不知道是否該繼續(xù)等待。
通過inteceptor,我們可以為所有的請求處理加一個loading:請求發(fā)送前顯示loading,接收響應(yīng)后隱藏loading。
具體步驟如下:
1.添加一個loading組件
<template id="loading-template"> <div class="loading-overlay"> <div class="sk-three-bounce"> <div class="sk-child sk-bounce1"></div> <div class="sk-child sk-bounce2"></div> <div class="sk-child sk-bounce3"></div> </div> </div> </template>
2.將loading組件作為另外一個Vue實(shí)例的子組件
var help = new Vue({ el: '#help', data: { showLoading: false }, components: { 'loading': { template: '#loading-template', } } })
3.將該Vue實(shí)例掛載到某個HTML元素
<div id="help"> <loading v-show="showLoading"></loading> </div>
4.添加inteceptor
Vue.http.interceptors.push((request, next) => { loading.show = true next((response) => { loading.show = false return response }); });
示例2
當(dāng)用戶在畫面上停留時間太久時,畫面數(shù)據(jù)可能已經(jīng)不是最新的了,這時如果用戶刪除或修改某一條數(shù)據(jù),如果這條數(shù)據(jù)已經(jīng)被其他用戶刪除了,服務(wù)器會反饋一個404的錯誤,但由于我們的put和delete請求沒有處理errorCallback,所以用戶是不知道他的操作是成功還是失敗了。
你問我為什么不在每個請求里面處理errorCallback,這是因?yàn)槲冶容^懶。這個問題,同樣也可以通過inteceptor解決。
1. 繼續(xù)沿用上面的loading組件,在#help元素下加一個對話框
<div id="help"> <loading v-show="showLoading" ></loading> <modal-dialog :show="showDialog"> <header class="dialog-header" slot="header"> <h1 class="dialog-title">Server Error</h1> </header> <div class="dialog-body" slot="body"> <p class="error">Oops,server has got some errors, error code: {{errorCode}}.</p> </div> </modal-dialog> </div>
2.給help實(shí)例的data選項(xiàng)添加兩個屬性
var help = new Vue({ el: '#help', data: { showLoading: false, showDialog: false, errorCode: '' }, components: { 'loading': { template: '#loading-template', } } })
3.修改inteceptor
Vue.http.interceptors.push((request, next) => { help.showLoading = true next((response) => { if(!response.ok){ help.errorCode = response.status help.showDialog = true } help.showLoading = false return response }); });
總結(jié)
vue-resource是一個非常輕量的用于處理HTTP請求的插件,它提供了兩種方式來處理HTTP請求:
- 使用Vue.http或this.$http
- 使用Vue.resource或this.$resource
這兩種方式本質(zhì)上沒有什么區(qū)別,閱讀vue-resource的源碼,你可以發(fā)現(xiàn)第2種方式是基于第1種方式實(shí)現(xiàn)的。
inteceptor可以在請求前和請求后附加一些行為,這意味著除了請求處理的過程,請求的其他環(huán)節(jié)都可以由我們來控制。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
vue.js引用背景圖background無效的3種解決方案
這篇文章主要介紹了vue.js引用背景圖background無效的3種解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08vue實(shí)現(xiàn)動態(tài)表單動態(tài)渲染組件的方式(1)
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)動態(tài)表單動態(tài)渲染組件的方式,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-04-04Vue Echarts實(shí)現(xiàn)圖表的動態(tài)適配以及如何優(yōu)化
這篇文章主要介紹了Vue Echarts實(shí)現(xiàn)圖表的動態(tài)適配以及如何優(yōu)化,在實(shí)際的前端開發(fā)過程中,動態(tài)適配是一個非常重要的問題,在數(shù)據(jù)可視化的場景下,圖表的動態(tài)適配尤為重要,需要的朋友可以參考下2023-05-05uniapp-ios開發(fā)之App端與webview端相互通信的方法以及注意事項(xiàng)
在uni-app與Webview之間進(jìn)行數(shù)據(jù)交互是非常常見的需求,下面這篇文章主要給大家介紹了關(guān)于uniapp-ios開發(fā)之App端與webview端相互通信的方法以及注意事項(xiàng)的相關(guān)資料,需要的朋友可以參考下2024-07-07Vue.js項(xiàng)目實(shí)戰(zhàn)之多語種網(wǎng)站的功能實(shí)現(xiàn)(租車)
這篇文章主要介紹了Vue.js項(xiàng)目實(shí)戰(zhàn)之多語種網(wǎng)站(租車)的功能實(shí)現(xiàn) ,需要的朋友可以參考下2019-08-08vue+element模態(tài)框中新增模態(tài)框和刪除功能
這篇文章主要介紹了vue+element模態(tài)框中新增模態(tài)框和刪除功能,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06