前后端分離后,它們之間主要的溝通方式是ajax請(qǐng)求響應(yīng)刨晴。vue官方的vue-resource屉来,和axios都可以實(shí)現(xiàn)路翻。這里講講使用axios來實(shí)現(xiàn)ajax請(qǐng)求狈癞。
安裝axios
npm i axios -S
開始使用
建立文件夾src/request/,所有ajax請(qǐng)求都在這里進(jìn)行茂契。
首先創(chuàng)建iaxios.js文件實(shí)例化axios
import axios from 'axios'
import utils from './utils'
const transformRequest = data => {
if (utils.isFormData(data) ||
utils.isArrayBuffer(data) ||
utils.isBuffer(data) ||
utils.isStream(data) ||
utils.isFile(data) ||
utils.isBlob(data) ||
utils.isArrayBufferView(data) ||
utils.isURLSearchParams(data)
) {
return data
}
if (utils.isObject(data)) {
for (var pkey in data) {
if (data[pkey] === null || typeof (data[pkey]) === 'undefined') {
delete data[pkey]
}
}
data = utils.params(data)
return data
}
return data
}
axios.defaults.transformRequest.unshift(transformRequest)
const instance = axios.create({
baseURL: process.env.VUE_APP_SERVER_PATH || location.protocol + '//' + location.host
})
instance.interceptors.request.use(config => {
// 可以在這里加入ajax請(qǐng)求前處理的業(yè)務(wù)蝶桶,如加入access_token
return config
})
instance.interceptors.response.use(response => {
return response.data
}, error => {
let response = error.response
return Promise.reject(response.data)
})
export default instance
這里有個(gè)函數(shù)transformRequest ,功能是把Object的參數(shù)轉(zhuǎn)換成String參數(shù)掉冶。這里考慮的是java作為服務(wù)端的時(shí)候真竖,Object的參數(shù)不能正確接收。如果服務(wù)端支持Json參數(shù)厌小。則不需要這個(gè)轉(zhuǎn)換器恢共。
axios.defaults.transformRequest.unshift(transformRequest)
這行代碼是向axios插入轉(zhuǎn)換器。
創(chuàng)建axios實(shí)例instance璧亚。下面是配置兩個(gè)實(shí)例的攔截器讨韭,像請(qǐng)求加入token,或者對(duì)所有的請(qǐng)求統(tǒng)一做一些處理癣蟋,或者對(duì)響應(yīng)的結(jié)果做一些處理等就可以在這里處理透硝。
最后export實(shí)例。
工具
在上面引入了utils.js文件疯搅,這里實(shí)現(xiàn)了一些工具濒生,主要參考了vue-resource源碼中的參數(shù)轉(zhuǎn)換的實(shí)現(xiàn)。vue-resource已經(jīng)考慮了向類似java服務(wù)器的傳參問題幔欧。下面是utils.js的代碼:
import _ from 'lodash'
var isBuffer = _.isBuffer
/* global toString:true */
// utils is a library of generic helper functions non-specific to axios
var toString = Object.prototype.toString
/**
* Determine if a value is an ArrayBuffer
*
* @param {Object} val The value to test
* @returns {boolean} True if value is an ArrayBuffer, otherwise false
*/
function isArrayBuffer (val) {
return toString.call(val) === '[object ArrayBuffer]'
}
/**
* Determine if a value is a FormData
*
* @param {Object} val The value to test
* @returns {boolean} True if value is an FormData, otherwise false
*/
function isFormData (val) {
return (typeof FormData !== 'undefined') && (val instanceof FormData)
}
/**
* Determine if a value is a view on an ArrayBuffer
*
* @param {Object} val The value to test
* @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false
*/
function isArrayBufferView (val) {
var result
if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) {
result = ArrayBuffer.isView(val)
} else {
result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer)
}
return result
}
/**
* Determine if a value is an Object
*
* @param {Object} val The value to test
* @returns {boolean} True if value is an Object, otherwise false
*/
function isObject (val) {
return val !== null && typeof val === 'object'
}
/**
* Determine if a value is a File
*
* @param {Object} val The value to test
* @returns {boolean} True if value is a File, otherwise false
*/
function isFile (val) {
return toString.call(val) === '[object File]'
}
/**
* Determine if a value is a Blob
*
* @param {Object} val The value to test
* @returns {boolean} True if value is a Blob, otherwise false
*/
function isBlob (val) {
return toString.call(val) === '[object Blob]'
}
/**
* Determine if a value is a Function
*
* @param {Object} val The value to test
* @returns {boolean} True if value is a Function, otherwise false
*/
function isFunction (val) {
return toString.call(val) === '[object Function]'
}
/**
* Determine if a value is a Stream
*
* @param {Object} val The value to test
* @returns {boolean} True if value is a Stream, otherwise false
*/
function isStream (val) {
return isObject(val) && isFunction(val.pipe)
}
/**
* Determine if a value is a URLSearchParams object
*
* @param {Object} val The value to test
* @returns {boolean} True if value is a URLSearchParams object, otherwise false
*/
function isURLSearchParams (val) {
return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams
}
/**
* Encodes a Url parameter string.
*
* @param {Object} obj
*/
function params (obj) {
let params = []
let escape = encodeURIComponent
params.add = function (key, value) {
if (_.isFunction(value)) {
value = value()
}
if (value === null) {
value = ''
}
this.push(escape(key) + '=' + escape(value))
}
serialize(params, obj)
return params.join('&').replace(/%20/g, '+')
}
function serialize (params, obj, scope) {
let array = _.isArray(obj)
let plain = _.isPlainObject(obj)
let hash = null
_.forEach(obj, (value, key) => {
hash = _.isObject(value) || _.isArray(value)
if (scope) {
key = scope + '[' + (plain || hash ? key : '') + ']'
}
if (!scope && array) {
params.add(value.name, value.value)
} else if (hash) {
serialize(params, value, key)
} else {
params.add(key, value)
}
})
}
export default {
isArrayBuffer: isArrayBuffer,
isBuffer: isBuffer,
isFormData: isFormData,
isArrayBufferView: isArrayBufferView,
isObject: isObject,
isFile: isFile,
isBlob: isBlob,
isStream: isStream,
isURLSearchParams: isURLSearchParams,
params: params
}
基礎(chǔ)實(shí)現(xiàn)
base.js罪治,導(dǎo)出基本的ajax請(qǐng)求函數(shù)丽声,這里只導(dǎo)出了get和post。更多的同理導(dǎo)出即可觉义。在所有ajax請(qǐng)求時(shí)恒序,都調(diào)用這里的函數(shù)完成。代碼如下:
import _ from 'lodash'
import iaxios from './iaxios'
const defaultPagination = {
current: 1,
size: 10
}
const paginationBody = (body, pagination) => {
let _body = _.cloneDeep(body || {})
pagination = _.defaultsDeep(pagination, defaultPagination)
let _pag = {
sort: pagination.sort || null,
order: pagination.order || null,
pageOffset: pagination.pageOffset || pagination.current || 1,
pageSize: pagination.pageSize || pagination.size || 10
}
return _.defaultsDeep(_body, _pag)
}
export default {
defaultPagination,
paginationBody,
get (url, options) {
return iaxios.get(url, options)
},
post (url, body, options) {
return iaxios.post(url, body, options)
}
}
說明:paginationBody用于把數(shù)據(jù)分頁參數(shù)與篩選參數(shù)合并起來谁撼。分頁參數(shù)根據(jù)服務(wù)端的命名進(jìn)行修改歧胁。如下面的一段請(qǐng)求:
import Service from '../base'
export default {
find (pagination, options) {
return Service.post('/userapi/user/user/find', Service.paginationBody(options, pagination))
}
}
在頁面組件中,把分頁和篩選的參數(shù)分開來記錄厉碟,使用vuex時(shí)喊巍,也可以分開維護(hù)狀態(tài)。請(qǐng)求時(shí)合并成一個(gè)對(duì)象箍鼓。
使用示例
如上面的find接口在頁面中的使用如下崭参。
<script>
import _ from 'lodash'
import UserService from '@/request/user/user'
export default {
name: 'AdminUserUser',
data () {
return {
options: {
name: null
},
pagination: {
sort: null,
order: null,
size: 10,
total: 0,
current: 1,
layout: 'total, sizes, prev, pager, next, jumper',
sizes: [10, 20, 30, 40, 50, 100]
},
users: []
}
},
methods: {
listUser () {
UserService.find(this.pagination, this.options).then(res => {
this.users = _.clone(res.result || [])
})
}
}
}
</script>