前后端分离后,它们之间主要的沟通方式是ajax请求响应。vue官方的vue-resource,和axios都可以实现。这里讲讲使用axios来实现ajax请求。
安装axios
npm i axios -S
开始使用
建立文件夹src/request/,所有ajax请求都在这里进行。
首先创建iaxios.js文件实例化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请求前处理的业务,如加入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
这里有个函数transformRequest ,功能是把Object的参数转换成String参数。这里考虑的是java作为服务端的时候,Object的参数不能正确接收。如果服务端支持Json参数。则不需要这个转换器。
axios.defaults.transformRequest.unshift(transformRequest)
这行代码是向axios插入转换器。
创建axios实例instance。下面是配置两个实例的拦截器,像请求加入token,或者对所有的请求统一做一些处理,或者对响应的结果做一些处理等就可以在这里处理。
最后export实例。
工具
在上面引入了utils.js文件,这里实现了一些工具,主要参考了vue-resource源码中的参数转换的实现。vue-resource已经考虑了向类似java服务器的传参问题。下面是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
}
基础实现
base.js,导出基本的ajax请求函数,这里只导出了get和post。更多的同理导出即可。在所有ajax请求时,都调用这里的函数完成。代码如下:
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用于把数据分页参数与筛选参数合并起来。分页参数根据服务端的命名进行修改。如下面的一段请求:
import Service from '../base'
export default {
find (pagination, options) {
return Service.post('/userapi/user/user/find', Service.paginationBody(options, pagination))
}
}
在页面组件中,把分页和筛选的参数分开来记录,使用vuex时,也可以分开维护状态。请求时合并成一个对象。
使用示例
如上面的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>