GitHub Source前端
本文的全部示例以下:vue
各位在閱讀這篇文章的內容時,能夠先嚐試該列表的最後兩個示例,這兩個示例綜合使用了this.$http和inteceptor。jquery
vue-resource插件具備如下特色:ajax
1. 體積小json
vue-resource很是小巧,在壓縮之後只有大約12KB,服務端啓用gzip壓縮後只有4.5KB大小,這遠比jQuery的體積要小得多。後端
2. 支持主流的瀏覽器api
和Vue.js同樣,vue-resource除了不支持IE 9如下的瀏覽器,其餘主流的瀏覽器都支持。跨域
3. 支持Promise API和URI Templates瀏覽器
Promise是ES6的特性,Promise的中文含義爲「先知」,Promise對象用於異步計算。
URI Templates表示URI模板,有些相似於ASP.NET MVC的路由模板。服務器
4. 支持攔截器
攔截器是全局的,攔截器能夠在請求發送前和發送請求後作一些處理。
攔截器在一些場景下會很是有用,好比請求發送前在headers中設置access_token,或者在請求失敗時,提供共通的處理方式。
<script src="js/vue.js"></script>
<script src="js/vue-resource.js"></script>
引入vue-resource後,能夠基於全局的Vue對象使用http,也能夠基於某個Vue實例使用http。
// 基於全局Vue對象使用http
Vue.http.get('/someUrl', [options]).then(successCallback, errorCallback);
Vue.http.post('/someUrl', [body], [options]).then(successCallback, errorCallback);
// 在一個Vue實例內使用$http
this.$http.get('/someUrl', [options]).then(successCallback, errorCallback);
this.$http.post('/someUrl', [body], [options]).then(successCallback, errorCallback);
在發送請求後,使用then
方法來處理響應結果,then
方法有兩個參數,第一個參數是響應成功時的回調函數,第二個參數是響應失敗時的回調函數。
then
方法的回調函數也有兩種寫法,第一種是傳統的函數寫法,第二種是更爲簡潔的ES 6的Lambda寫法:
// 傳統寫法
this.$http.get('/someUrl', [options]).then(function(response){
// 響應成功回調
}, function(response){
// 響應錯誤回調
});
// Lambda寫法
this.$http.get('/someUrl', [options]).then((response) => {
// 響應成功回調
}, (response) => {
// 響應錯誤回調
});
PS:作過.NET開發的人想必對Lambda寫法有一種熟悉的感受。
vue-resource的請求API是按照REST風格設計的,它提供了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名稱是標準的HTTP方法。當服務端使用REST API時,客戶端的編碼風格和服務端的編碼風格近乎一致,這能夠減小前端和後端開發人員的溝通成本。
客戶端請求方法 | 服務端處理方法 |
---|---|
this.$http.get(...) | Getxxx |
this.$http.post(...) | Postxxx |
this.$http.put(...) | Putxxx |
this.$http.delete(...) | Deletexxx |
發送請求時的options選項對象包含如下屬性:
參數 | 類型 | 描述 |
---|---|---|
url | string |
請求的URL |
method | string |
請求的HTTP方法,例如:'GET', 'POST'或其餘HTTP方法 |
body | Object ,FormData string |
request body |
params | Object |
請求的URL參數對象 |
headers | Object |
request header |
timeout | number |
單位爲毫秒的請求超時時間 (0 表示無超時時間) |
before | function(request) |
請求發送前的處理函數,相似於jQuery的beforeSend函數 |
progress | function(event) |
ProgressEvent回調處理函數 |
credientials | boolean |
表示跨域請求時是否須要使用憑證 |
emulateHTTP | boolean |
發送PUT, PATCH, DELETE請求時以HTTP POST的方式發送,並設置請求頭的X-HTTP-Method-Override |
emulateJSON | boolean |
將request body以application/x-www-form-urlencoded content type發送 |
若是Web服務器沒法處理PUT, PATCH和DELETE這種REST風格的請求,你能夠啓用enulateHTTP現象。啓用該選項後,請求會以普通的POST方法發出,而且HTTP頭信息的X-HTTP-Method-Override
屬性會設置爲實際的HTTP方法。
Vue.http.options.emulateHTTP = true;
若是Web服務器沒法處理編碼爲application/json的請求,你能夠啓用emulateJSON選項。啓用該選項後,請求會以application/x-www-form-urlencoded
做爲MIME type,就像普通的HTML表單同樣。
Vue.http.options.emulateJSON = true;
response對象包含如下屬性:
方法 | 類型 | 描述 |
---|---|---|
text() | string |
以string形式返回response body |
json() | Object |
以JSON對象形式返回response body |
blob() | Blob |
以二進制形式返回response body |
屬性 | 類型 | 描述 |
ok | boolean |
響應的HTTP狀態碼在200~299之間時,該屬性爲true |
status | number |
響應的HTTP狀態碼 |
statusText | string |
響應的狀態文本 |
headers | Object |
響應頭 |
注意:本文的vue-resource版本爲v0.9.3,若是你使用的是v0.9.0之前的版本,response對象是沒有json(), blob(), text()這些方法的。
提示:如下示例仍然沿用上一篇的組件和WebAPI,組件的代碼和頁面HTML代碼我就再也不貼出來了。
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只在響應失敗時調用,而catch則是在整個請求到響應過程當中,只要程序出錯了就會被調用。
在then方法的回調函數內,你也能夠直接使用this,this仍然是指向Vue實例的:
getCustomers: function() {
this.$http.get(this.apiUrl)
.then((response) => {
this.$set('gridData', response.data)
})
.catch(function(response) {
console.log(response)
})
}
爲了減小做用域鏈的搜索,建議使用一個局部變量來接收this。
View Demo
getCustomers: function() {
this.$http.jsonp(this.apiUrl).then(function(response){
this.$set('gridData', response.data)
})
}
View Demo
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
}
}
})
View Demo
updateCustomer: function() {
var vm = this
vm.$http.put(this.apiUrl + '/' + vm.item.customerId, vm.item)
.then((response) => {
vm.getCustomers()
})
}
View Demo
deleteCustomer: function(customer){
var vm = this
vm.$http.delete(this.apiUrl + '/' + customer.customerId)
.then((response) => {
vm.getCustomers()
})
}
View Demo
vue-resource提供了另一種方式訪問HTTP——resource服務,resource服務包含如下幾種默認的action:
get: {method: 'GET'},
save: {method: 'POST'},
query: {method: 'GET'},
update: {method: 'PUT'},
remove: {method: 'DELETE'},
delete: {method: 'DELETE'}
resource對象也有兩種訪問方式:
Vue.resource
this.$resource
resource能夠結合URI Template一塊兒使用,如下示例的apiUrl都設置爲{/id}了:
apiUrl: 'http://211.149.193.19:8080/api/customers{/id}'
使用get方法發送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)
})
}
View Demo
使用save方法發送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
}
View Demo
使用update方法發送PUT請求,下面這個請求指定了{/id}
。
updateCustomer: function() {
var resource = this.$resource(this.apiUrl)
vm = this
resource.update({ id: vm.item.customerId}, vm.item)
.then((response) => {
vm.getCustomers()
})
}
{/id}
至關於一個佔位符,當傳入實際的參數時該佔位符會被替換。
例如,{ id: vm.item.customerId}
中的vm.item.customerId爲12,那麼發送的請求URL爲:
http://211.149.193.19:8080/api/customers/12
View Demo
使用remove或delete方法發送DELETE請求,下面這個請求指定了{/id}
。
deleteCustomer: function(customer){
var resource = this.$resource(this.apiUrl)
vm = this
resource.remove({ id: customer.customerId})
.then((response) => {
vm.getCustomers()
})
}
View Demo
攔截器能夠在請求發送前和發送請求後作一些處理。
Vue.http.interceptors.push((request, next) => {
// ...
// 請求發送前的處理邏輯
// ...
next((response) => {
// ...
// 請求發送後的處理邏輯
// ...
// 根據請求的狀態,response參數會返回給successCallback或errorCallback
return response
})
})
在response返回給successCallback或errorCallback以前,你能夠修改response中的內容,或作一些處理。
例如,響應的狀態碼若是是404,你能夠顯示友好的404界面。
若是不想使用Lambda函數寫法,能夠用平民寫法:
Vue.http.interceptors.push(function(request, next) {
// ...
// 請求發送前的處理邏輯
// ...
next(function(response) {
// ...
// 請求發送後的處理邏輯
// ...
// 根據請求的狀態,response參數會返回給successCallback或errorCallback
return response
})
})
以前的CURD示例有一處用戶體驗不太好,用戶在使用一些功能的時候若是網絡較慢,畫面又沒有給出反饋,用戶是不知道他的操做是成功仍是失敗的,他也不知道是否該繼續等待。
經過inteceptor,咱們能夠爲全部的請求處理加一個loading:請求發送前顯示loading,接收響應後隱藏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實例的子組件
var help = new Vue({
el: '#help',
data: {
showLoading: false
},
components: {
'loading': {
template: '#loading-template',
}
}
})
3.將該Vue實例掛載到某個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
});
});
View Demo
當用戶在畫面上停留時間過久時,畫面數據可能已經不是最新的了,這時若是用戶刪除或修改某一條數據,若是這條數據已經被其餘用戶刪除了,服務器會反饋一個404的錯誤,但因爲咱們的put和delete請求沒有處理errorCallback,因此用戶是不知道他的操做是成功仍是失敗了。
你問我爲何不在每一個請求裏面處理errorCallback,這是由於我比較懶。這個問題,一樣也能夠經過inteceptor解決。
1. 繼續沿用上面的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實例的data選項添加兩個屬性
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
});
});
View Demo
vue-resource是一個很是輕量的用於處理HTTP請求的插件,它提供了兩種方式來處理HTTP請求:
這兩種方式本質上沒有什麼區別,閱讀vue-resource的源碼,你能夠發現第2種方式是基於第1種方式實現的。
inteceptor能夠在請求前和請求後附加一些行爲,這意味着除了請求處理的過程,請求的其餘環節均可以由咱們來控制。