本文为vue/cli2.x下src目录中http篇,项目结构参照vue-cli 2.x项目模板文件说明(一)整体结构篇
本目录文件参考 这里,对本目录有疑问可以进行参照斧正,下面是单个文件内容
(1) config.js
export default {
method: 'post',
//基础路径前缀,如有多个可在请求中单独设置
baseURL: 'https://cnodejs.org/api/',
// 请求头信息,这里建议与服务端同学进行约定
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
},
// 参数
data: {},
// 设置超时时间
timeout: 3000,
// 携带凭证
withCredentials: true,
// 返回数据类型
responseType: 'json'
}
(2)api.js
import axios from 'axios' // 这里要先安装axios后方可引入
import config from '@/http/config.js' //导入配置文件
import qs from 'qs' // 序列化请求数据,看服务端要求
import Vue from 'vue' //本条导入以及下条导入,是为了应用vux UI框架的提示功能 ,可参考自身项目框架进行修改
import { ToastPlugin } from 'vux' // 从vux中引入提示功能
Vue.use(ToastPlugin, {position: 'middle'}) // vux提示功能设置并挂载
export default function $axios (options) {
return new Promise((resolve, reject) => {
const instance = axios.create({
baseURL: config.baseURL,
headers: config.headers,
transformResponse: [function (data) {}]
})
// request 拦截器
instance.interceptors.request.use(
config => {
// Tip: 1
// 请求开始的时候可以结合 vuex 开启全屏的 loading 动画
// Tip: 2
// 带上 token , 可以结合 vuex 或者重 localStorage
// if (store.getters.token) {
// config.headers['X-Token'] = getToken() // 让每个请求携带token--['X-Token']为自定义key 请根据实际情况自行修改
// } else {
// 重定向到登录页面
// }
// Tip: 3
// 根据请求方法,序列化传来的参数,根据服务端需求是否序列化
if (config.method.toLocaleLowerCase() === 'put' ||
config.method.toLocaleLowerCase() === 'delete') {
config.data = qs.stringify(config.data)
}
if (config.method.toLocaleLowerCase() === 'post') {
config.data = {...config.data, static_req: 'lyww1992'} // 此处为设置每次请求必带字符串 ...运算符可自行参考ES6
config.data = qs.stringify(config.data)
console.log(config.data)
}
return config
},
error => {
// 请求错误时做些事(接口错误、超时等)
// Tip: 4
// 关闭loadding
console.log('request:', error)
// 判断请求超时
if (error.code === 'ECONNABORTED' && error.message.indexOf('timeout') !== -1) {
console.log('根据你设置的timeout/真的请求超时 判断请求现在超时了,你可以在这里加入超时的处理方案')
// return service.request(originalRequest);//例如再重复请求一次
}
return Promise.reject(error) // 在调用的那边可以拿到(catch)你想返回的错误信息
}
)
// response 拦截器
instance.interceptors.response.use(
response => {
console.log(response)
let texturl = response.config.url
let data
// IE9时response.data是undefined,因此需要使用response.request.responseText(Stringify后的字符串
if (response.data === undefined) {
data = response.request.responseText
} else {
data = response.data
}
data = JSON.parse(data) // 此行是默认将所有返回字符串处理为json格式,如有不同,请将该行代码删除,在具体使用时单独转化
// 根据返回的code值来做不同的处理(和服务端约定)
switch (data.errorno) {
case '200':
break
default:
}
return data
},
err => {
if (err && err.response) {
switch (err.response.status) {
case 400:
err.message = '请求错误'
break
case 401:
err.message = '未授权,请登录'
break
case 403:
err.message = '拒绝访问'
break
case 404:
err.message = `请求地址出错: ${err.response.config.url}`
break
case 408:
err.message = '请求超时'
break
case 500:
err.message = '服务器内部错误'
break
case 501:
err.message = '服务未实现'
break
case 502:
err.message = '网关错误'
break
case 503:
err.message = '服务不可用'
break
case 504:
err.message = '网关超时'
break
case 505:
err.message = 'HTTP版本不受支持'
break
default:
}
}
console.error(err)
/* 这部分是vux提示组件应用
this.$vux.toast.show({
text: err,
time: 800,
width: '3.75rem'
})
*/
return Promise.reject(err) // 返回接口返回的错误信息
}
)
// 请求处理
instance(options)
.then((res) => {
resolve(res)
return false
})
.catch((error) => {
reject(error)
})
})
}
(3) interface.js
这部分是所有API接口统一管理目录 (以cnode.js提供的API为例)
简要说明下这部分
a. 请求类型与参数
get请求时参数设置是params,post请求时参数设置是data!!!
get请求时参数设置是params,post请求时参数设置是data!!!
get请求时参数设置是params,post请求时参数设置是data!!!
没有为什么,axios的官方规定,其他类型请求请参照axios中文文档
b. 接口部分若是存在不同源,比如示例中的getText,它的请求有本身与其它接口不同,且存在多个来源,建议单独配置url(本示例中的url均是经过config/index.js的proxyTable代理,关于这部分可参照我的另一篇博文vue-cli config下index.js中各条解析及proxyTable配置)
import axios from '@/http/api' // 导入 api
// 单独导出
// 主题首页
export const getTopicHome = params => {
return axios({
url: '/api/v1/topics',
method: 'get',
params
})
}
// 主题收藏
export const topicCollect= data => {
return axios({
url: '/api/v1/topic_collect/collect',
method: 'post',
data
})
}
// 请求另一接口且接口本身有多个来源时
export const getText = (textlocal, singleUrl, params) => {
let pro
let rega = /dwtxt/, regb=/dwext/;
if (textlocal.match(rega)) {
pro = '/resource1'
}
if (textlocal .match(regb)) {
pro = '/resource2'
}
return axios({
url: pro + singleUrl,
method: 'get',
params
})
}
// 默认全部倒出
export default {
getTopicHome,
topicCollect,
getText
}
(4). index.js
// 导入所有接口
import apiList from '@/http/interface'
const install = Vue => {
if (install.installed) {
return
}
install.installed = true
Object.defineProperties(Vue.prototype, {
// 此处挂载在 Vue 原型的 $api 对象上
$api: {
get () {
return apiList
}
}
})
}
export default install
(5)使用说明
在main.js中挂载
import api from '@/http/index' // 异步请求
Vue.use(api)
在*.vue文件中调用
// 调用主题首页
this.$api.getTopicHome()
.then(data => {
consoel.log(data) // 这是请求成功后的回调数据
})
.catch(() => {
console.log('请求出错')
})
//调用主题收藏
this.$api.topicCollect({topic_id: 5433d5e4e737cbe96dcef312})
.then(data => {
consoel.log(data) // 这是请求成功后的回调数据
})
.catch(() => {
console.log('请求出错')
})