任何一个系统,和后端的数据交互都是必要的。vue 项目推荐使用 axios
安装
npm install axios
使用
第一种方式,将 axios 添加到 Vue 原型上。(不推荐)
// main.js
import Vue from 'vue'
import App from './App.vue'
import './registerServiceWorker'
import router from './router'
import store from './store'
import axios from 'axios'
import './plugins/element'
import './assets/scss/main.scss'
Vue.config.productionTip = false
Vue.prototype.$axios = axios
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
// user.vue
queryInfo () {
this.$axios.get('url').then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
}
在实际的项目开发中,不推荐这种使用方式。主要原因是这种书写方式,请求地址与业务逻辑写在一起,不利于代码维护。如果一个接口多个地方使用,一旦接口地址或者传参有变化,需要修改多个地方。我平时喜欢将接口地址放到统一的地方管理并维护。
第二种方式,对 axios 进行简易封装(推荐)
1. axios引入并添加拦截器
在 src 文件夹下新建 api 文件夹,用于存放所有的接口文件。
在 api 文件夹下新建 index.js,引入 axios ,并添加拦截器
// index.js
import axios from 'axios'
import router from '@/router/index'
import { Message } from 'element-ui'
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_URL, // url = base url + request url
timeout: 60000 * 10 // request timeout
})
// 添加请求拦截器,在请求头中加token
service.interceptors.request.use(
config => {
if (localStorage.getItem('token')) {
config.headers.token = localStorage.getItem('token')
}
return config
},
error => {
return Promise.reject(error)
})
// 添加响应拦截器,对返回结果做统一处理
service.interceptors.response.use(function (response) {
const status = response.data.success
if (status === undefined) { // 下载接口返回文件流
return response
} else if (status) {
return response.data.data
} else {
const errorCode = response.data.errorCode
const messages = response.data.message
// token过期
if (errorCode === 401) {
Message.warning('您的登录状态已过期,请重新登录')
localStorage.removeItem('token')
localStorage.removeItem('userInfo')
router.push({ path: '/login' })
return Promise.reject(response.data)
}
if (messages) {
Message.error(messages)
return Promise.reject(response.data)
} else {
Message.error('操作失败')
return Promise.reject(response.data)
}
}
}, function (error) {
// Do something with response error
Message.error('服务器异常')
return Promise.reject(error)
})
export default service
axios 的拦截器有两种,请求拦截器和响应拦截器。
通常我们会在请求拦截器中,给每一个请求的 header 加上 token ,便于鉴权。
在响应拦截器中,对返回的数据做统一的处理。我们公司,前端与后端的约定是,response 的 data 中, success 为 true 则请求成功,否则请求失败,失败时,会返回 errorCode 和 message。但是对于一些下载的接口,data 则直接返回文件流。所以我的响应拦截器中分了三种情况。大家在开发中,可根据项目的情况,对拦截器加以修改。
2. 对常用的请求方式进行封装
在 api 文件夹下新建 service.js,对常用的请求方式进行简易的封装
// service.js
import service from './index'
export const baseService = function (url, data = {}, method = 'GET', header = {}, responseType = 'json') {
// 校验 URL 必需
if (!url) {
console.log('请传入 request 地址')
return
}
// 请求方式转为大写
method = method.toLocaleUpperCase()
const config = {
url: url,
method: method,
headers: header,
responseType: responseType // 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
}
if (method === 'GET' || method === 'DELETE') {
config.params = data
}
if (method === 'POST' || method === 'PUT' || method === 'PATCH') {
config.data = data
}
return service(config)
.then(response => {
return response
}).catch(err => {
return Promise.reject(err)
})
}
export const getService = function (url, data, header, responseType) {
return baseService(url, data, 'GET', header, responseType)
}
export const deleteService = function (url, data, header, responseType) {
return baseService(url, data, 'DELETE', header, responseType)
}
export const postService = function (url, data, header, responseType) {
return baseService(url, data, 'POST', header, responseType)
}
export const putService = function (url, data, header, responseType) {
return baseService(url, data, 'PUT', header, responseType)
}
这里只对 get,post,put,delete 这四种常见的请求方式进行了封装。
这里需要注意两点:
- get 和 post 的传参方式不一样,delete 同 get ,put 同 post
- responseType 这个参数是必要的,对于上传下载的接口,数据为文件流,responseType 需设置为arraybuffer
3. 使用
建议大家根据模块创建对应的 js 文件,每个 js 文件,维护自己模块下的接口。
例如,login.js 用来维护登录相关的接口。
// login.js
import { getService, postService } from './service'
/**
* name 登录
* time 2021-09-07
* param userName String 账号
* param password String 密码
* return String token
* */
export const signIn = params => {
return postService('/anon/login', params)
}
/**
* name 登出
* time 2021-09-07
* */
export const signOut = params => {
return getService('/auth/logout', params)
}
// login.vue
import { signIn } from '@/api/login'
export default {
name: 'login',
data () {
return {
userInfo: {}
}
},
methods: {
login () {
const params = this.userInfo
signIn(params).then(res => {
console.log(res)
})
}
}
}
以上,就是我在项目中使用 axios 的解决方案。
项目地址:
系列文章:
vue-cli3+ 搭建pc端管理项目(二, 不同环境配置[开发,测试,生产])