axios参考:https://github.com/axios/axios、http://www.axios-js.com/zh-cn/docs/#axios-delete-url-config-1、https://axios.nuxtjs.org/usage
axios封装参考:https://blog.csdn.net/weixin_44356673/article/details/107467614
nuxt使用参考:https://blog.csdn.net/qq_41387882/article/details/106294485
axios的封装
在plugins中创建axios_interceptors.js文件,封装axios
const qs = require('qs');import Vue from 'vue'export default function ({ $axios, store }, inject) {const myAxios = $axios.create({timeout: 1000 * 60})// ! 响应的拦截/*** todo 提示函数* 禁止点击蒙层、显示一秒后关闭*/const tip = msg => {Vue.prototype.$message.error(msg, 10);}/*** todo 跳转登录页* 携带当前页面路由,以期在登录页面完成登录后返回当前页面*/const toLogin = () => {// router.replace({// path: '/login',// query: {// redirect: router.currentRoute.fullPath// }// })window.onNuxtReady(() => {window.$nuxt.$router.replace({path: '/login',query: {// 保存上一个页面的访问路径redirect: router.currentRoute.fullPath}})})}/*** todo 请求失败后的错误统一处理* @param {Number} status 请求失败的状态码*/const errorHandle = (status, msg) => {switch (status) {// 401: 未登录// 1. 跳转登录页面,并携带当前页面的路径// 2. 在登录成功后返回当前页面,这一步需要在登录页操作。case 401:toLogin()break// 403 token过期// 登录过期对用户进行提示// 清除本地token和清空vuex中token对象// 跳转登录页面case 403:tip('登录过期,请重新登录')// 清除tokenlocalStorage.removeItem('token')store.commit('loginSuccess', null)// 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面setTimeout(() => {toLogin()}, 1000)break// 404请求不存在case 404:tip('网络请求不存在')breakcase 504:tip('服务器错误')break// 其他错误,直接抛出错误提示default:tip(msg)break}}// todo 移除 lodingconst removeLoding = (url) => {console.log(url, 'removeLoading');store.commit('loading/removeLoadingCount');}// todo 请求拦截myAxios.onRequest(config => {// todo 解决get请求传递数组参数出现 [ ] 解决方法if (config.method === 'get') {// 格式化get的请求参数config.paramsSerializer = function (params) {// qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' }) // 'a[0]=b&a[1]=c'// qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' }) // 'a[]=b&a[]=c'// qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' }) // 'a=b&a=c'return qs.stringify(params, { arrayFormat: 'repeat' })}}// 登录流程控制中,根据本地是否存在token判断用户的登录情况// 但是即使token存在,也有可能token是过期的,所以在每次的请求头中携带token// 后台根据携带的token判断用户的登录情况,并返回给我们对应的状态码// 而后我们可以在响应拦截器中,根据状态码进行一些统一的操作。const token = store.state.tokentoken && (config.headers.Authorization = token)return config})// todo 请求失败myAxios.onRequestError(error => Promise.error(error))// todo 返回成功// 如果返回的状态码为200 并且为ACK,说明接口请求成功,可以正常拿到数据// 否则的话抛出错误myAxios.onResponse(res => {removeLoding(res.config.url) // 移除loading// console.log(res, '=====');return res.status === 200 ? Promise.resolve(res) : Promise.reject(res)})// todo 返回失败// 这里可以跟你们的后台开发人员协商好统一的错误状态码// 然后根据返回的状态码进行一些操作,例如登录过期提示,错误提示等等// 下面列举几个常见的操作,其他需求可自行扩展myAxios.onResponseError(error => {removeLoding() // 移除loadingconsole.log(error, '======')const { response } = errorconsole.log(response)if (response) {// 请求已发出,但是不在2xx的范围errorHandle(response.status, response.data.message)return Promise.reject(response)} else {console.log('========================== aaa');// 处理断网的情况// eg:请求超时或断网时,更新state的network状态// network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏// 关于断网组件中的刷新重新获取数据,会在断网组件中说明store.commit('changeNetwork', false)}})// 重写axios的方法----统一处理请求参数myAxios.$get = (...arg) => {return fn('get', ...arg)}myAxios.$post = (...arg) => {return fn('post', ...arg)}myAxios.$put = (...arg) => {return fn('put', ...arg)}/*** ! 公共请求方法* @param {String} url [请求的url地址]* @param {Object} params [请求时携带的参数]* @param {Object} options [其他配置]* 如果返回500,是因为后台判断不是ajax请求,需要传递 headersheaders: {'x-requested-with': 'XMLHttpRequest',"x-form-id": "mob-form"}*/function fn (methods, ...arg) {let [url, params, options = {}] = arglet opts = Object.assign({loading: true,tip: true}, options)// 添加loadingif (opts.loading) {console.log(url, 'loding', methods);store.commit('loading/addLoadingCount')}const baseUrl = process.env.baseURLreturn new Promise((resolve, reject) => {// axios的请求要求是get或delete的时候参数是放在对象中的params下面的params = methods === 'get' || methods === 'delete' ? { params } : paramslet requestData = {}if (opts.headers) {requestData.headers = opts.headers}myAxios[methods](baseUrl + url, params, requestData).then(res => {if (res && res.data && res.data.code === 'ACK') {resolve(res.data)} else {(res && opts.tip) && tip(res.data.message)reject(res)}})})}// myAxios.myGet = function () {}// Inject to context as $apiinject('myAxios', myAxios)}
使用封装的axios
在plugins中创建api/api.js
// 接收inject的myAxiosexport default function({$myAxios, store}, inject) {inject('api', {// 因为$myAxios无法获取,所以只能传入user: require('./user.js').mount($myAxios),})}
user.js
export function mount (axios) {return {// 获取用户信息getUser: async (id, ...arg) => {return await axios.$post('/sys-user/' + id, ...arg)},}}
使用用户信息接口
// todo 第一种this.$api.user.getUser('11', {param: 11}, {loading: false}).then(result => {// 成功的回调}, err => {失败的回调})// todo 第二种les result = await this.$api.user.getUser('11', {param: 11}, {loading: false}).catch((err) => {// 捕捉异常的情况console.log(err)})
插件在nuxt.js中的配置
plugins: ['@/plugins/antd-ui', // UI框架"@/plugins/axios_interceptors", // 在client和service上生效"@/plugins/api/api", // 在client和service上生效],// 使用axios的模块// Modules: https://go.nuxtjs.dev/config-modulesmodules: ['@nuxtjs/axios','@nuxtjs/style-resources'],
