1.先引入

import axios from 'axios'
import qs from 'qs'
import router from '../router';
import store from '../store/index';
// 创建axios实例
var instance = axios.create({ timeout: 1000 * 12});
// 设置post请求头
// instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; (可以不在这里封装) // 拦截器
instance.interceptors.request.use(
config => {
// 登录流程控制中,根据本地是否存在token判断用户的登录情况
// 但是即使token存在,也有可能token是过期的,所以在每次的请求头
中携带token
// 后台根据携带的token判断用户的登录情况,并返回给我们对应的状态

// 而后我们可以在响应拦截器中,根据状态码进行一些统一的操作。
const token = store.state.token;
token && (config.headers.Authorization = token);
return config;
},
error => Promise.error(error)
)
// 响应拦截器 instance.interceptors.response.use(  // 请求成功

        res => res.status === 200 ? Promise.resolve(res) : Promise.reject(res),
   // 请求失败
        error => {
            const { response } = error;
            if (response) {
   // 请求已发出,但是不在2xx的范围
                  errorHandle(response.status, response.data.message);
                  return Promise.reject(response);
             } else {
          // 处理断网的情况
          // eg:请求超时或断网时,更新state的network状态
          // network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏
          // 关于断网组件中的刷新重新获取数据,会在断网组件中说明
          store.commit('changeNetwork', false);
          }
   });

1.去掉了之前get和post方法的封装,通过创建一个axios实例然后export default方法导出,这样使用起来更灵活一些。

2.去掉了通过环境变量控制baseUrl的值。考虑到接口会有多个不同域名的情况,所以准备通过js变量来控制接口域名。这点具体在api里会介绍。

3.增加了请求超时,即断网状态的处理。说下思路,当断网时,通过更新vuex中network的状态来控制断网提示组件的显示隐藏。断网提示一般会有重新加载数据的操作,这步会在后面对应的地方介绍。

4.公用函数进行抽出,简化代码,尽量保证单一职责原则。


// 一些方法的封装

/**
* 跳转登录页
* 携带当前页面路由,以期在登录页面完成登录后返回当前页面
*/
const toLogin = () => {
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
}

/**
* 请求失败后的错误统一处理
* @param {Number} status 请求失败的状态码
*/
   const errorHandle = (status, other) => {
       // 状态码判断
       switch (status) {
       // 401: 未登录状态,跳转登录页   
           case 401:
           toLogin();
           break;
       // 403 token过期
       // 清除token并跳转登录页
           case 403:
           tip('登录过期,请重新登录');
           localStorage.removeItem('token');
           store.commit('loginSuccess', null);
           setTimeout(() => {
                 toLogin();
           }, 1000);
          break;
      // 404请求不存在
           case 404:
           tip('请求的资源不存在');
         break;
         default:
         console.log(other);
   }}



article.js:

/**
* article模块接口列表
*/ import base from './base'; // 导入接口域名列表
import axios from '@/utils/http'; // 导入http中创建的axios实例
import qs from 'qs'; // 根据需求是否导入qs模块 const article = {
// 新闻列表
articleList () {
return axios.get(`${base.sq}/topics`);
},
// 新闻详情,演示
articleDetail (id, params) {
return axios.get(`${base.sq}/topic/${id}`, {
params: params
});
},
// post提交
login (params) {
return axios.post(`${base.sq}/accesstoken`, qs.stringify(params));
}
// 其他接口…………
} export default article;

index.js:

这里这里呢新建了一个api文件夹,里面有一个index.js和一个base.js,以及多个根据模块划分的接口js文件。index.js是一个api的出口,base.js管理接口域名,其他js则用来管理各个模块的接口。

/**
* api接口的统一出口
*/
// 文章模块接口
import article from '@/api/article';
// 其他模块的接口…… // 导出接口
export default {
article,
// ……
}

base.js:

/**
* 接口域名的管理
*/
const base = {
sq: 'https://xxxx111111.com/api/v1',
bd: 'http://xxxxx22222.com/api'
} export default base;

.请求的配置更灵活,你可以针对某个需求进行一个不同的配置。关于配置的优先级,axios文档说的很清楚,这个顺序是:在 lib/defaults.js 找到的库的默认值,然后是实例的 defaults 属性,最后是请求的 config 参数。后者将优先于前者。

最后,为了方便api的调用,我们需要将其挂载到vue的原型上。在main.js中

import Vue from 'vue'
import App from './App'
import router from './router' // 导入路由文件
import store from './store' // 导入vuex文件
import api from './api' // 导入api接口 Vue.prototype.$api = api; // 将api挂载到vue的原型上

在页面中这样调用接口:

methods: {
onLoad(id) {
this.$api.article.articleDetail(id, {
api: 123
}).then(res=> {
// 执行某些操作
})
}
}

再提一下断网的处理,这里只做一个简单的示例

<template>
<div id="app">
<div v-if="!network">
<h3>我没网了</h3>
<div @click="onRefresh">刷新</div>
</div>
<router-view/>
</div>
</template> <script>
import { mapState } from 'vuex';
export default {
name: 'App',
computed: {
...mapState(['network'])
},
methods: {
// 通过跳转一个空页面再返回的方式来实现刷新当前页面数据的目的
onRefresh () {
this.$router.replace('/refresh')
}
}
}
</script>
// refresh.vue
beforeRouteEnter (to, from, next) {
next(vm => {
vm.$router.replace(from.fullPath)
})
}

至此全部完结。文章参考博客喵容 - 和你一起描绘生活

这下面贴一下自己封装的。比上面稍简单些,灵活度不是很高,但适合小白,初学者配置使用,算是很实用吧。

import axios from 'axios'
// import qs from 'qs'
axios.interceptors.request.use(config => {
let append = document.getElementsByName('body')
append.innerHTML = '<img style="position:fixed;\n' +
' left:47%;\n' +
' top:40%;\n' +
' transform: translateY(-50%),translateX(-50%);"' +
' src="../../static/img/loading2.gif"/>'
return config
}, err => {
return Promise.resolve(err)
}) let base= ‘’ // 接口域名 export const request = (url, params,method,Func,isJson) => {
// let _this = this;
axios({
method: method,
url: `${base}${url}`,
data: method=== 'post'? params: '',
transformRequest: [function (data) {
if(isJson === 1) {
// debugger // 判断是否json格式或者是表单提交形式
return JSON.stringify(data)
}
let ret = ''
for (let it in data) {
ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'
}
return ret // 便于直接取到内部data
}],
headers: {
// 认证和请求方式
'Content-Type': isJson === 1 ? 'application/json' :
'application/x-www-form-urlencoded',
'authorization':sessionStorage.getItem('principal'),
'token':sessionStorage.getItem('token')
},
params: method=== 'get'? params: '',
}).then(data=>{
console.log(data)
if (data.data.code === 200) {
Func(data.data.data)
}else if(data.data.code === 406){
alert(data.data.message)
}else if(data.data.code === 401){
window.location.href=''//上线用这个地址
// window.location.href='/'
}else if(data.data.code === 400 || data.data.code === 505 || data.data.code === 404|| data.data.code === 500){
alert('网络异常')
}else if(data.data.code === 4011){
// window.location.href = '' //本地
window.location.href = '' //线上
}else if(data.data.code === 4012){
console.log(1111)
request('token/refresh',{
'authorization': sessionStorage.getItem('principal'),
'refreshToken': sessionStorage.getItem('refreshToken')
},'get',(res)=>{
//缓存新的token
console.log(res)
let token = res.token;
let principal = res.principal;
let refreshToken = res.refreshToken;
sessionStorage.setItem("token", token);
sessionStorage.setItem("principal", principal);
sessionStorage.setItem("refreshToken", refreshToken);
request(url, params,method,Func);
});
}
})
} // post
export const postRequest = (url, params,Func,isJson) => {
request(url, params,'post',Func,isJson)
} // uploadFileRequest 图片上传
export const uploadFileRequest = (url, params) => {
return axios({
method: 'post',
url: `${base}${url}`,
data: params,
headers: {
'Content-Type': 'multipart/form-data',
'authorization':sessionStorage.getItem('principal'),
'token':sessionStorage.getItem('token')
// 'authorization':'admin',
// 'token':'740a1d6be9c14292a13811cabb99950b'
}
})
} // get export const getRequest = (url, params,Func,isJson) => {
request(url, params,'get',Func,isJson)
}
main.js 引入

import {getRequest,postRequest} from './api/http'
Vue.prototype.$getRequest = getRequest;
Vue.prototype.$postRequest = postRequest;

至此结束了。相比配置只有两个文件,比较清晰。

一个完整实用的axios封装的更多相关文章

  1. vue-cli3中axios如何跨域请求以及axios封装

    1. vue.config.js中配置如下 module.exports = { // 选项... // devtool: 'eval-source-map',//开发调试 devServer: { ...

  2. vue2.0 axios封装、vuex介绍

    一.前言 博主也是vue道路上的行者,道行不深,希望自己的东西能对大家有所帮助.这篇博客针对 了解过vue基础,但是没有做过vue项目的童鞋.如果想看基础指令,可以看我之前的一篇博客,请点击  跳转, ...

  3. 把axios封装为vue插件使用

    前言 自从Vue2.0推荐大家使用 axios 开始,axios 被越来越多的人所了解.使用axios发起一个请求对大家来说是比较简单的事情,但是axios没有进行封装复用,项目越来越大,引起的代码冗 ...

  4. 【如何快速的开发一个完整的iOS直播app】(播放篇)

    原文转自:袁峥Seemygo    感谢分享.自我学习 前言 在看这篇之前,如果您还不了解直播原理,请查看上篇文章如何快速的开发一个完整的iOS直播app(原理篇) 开发一款直播app,集成ijkpl ...

  5. 【如何快速的开发一个完整的iOS直播app】(原理篇)

    原文转自:袁峥Seemygo    感谢分享.自我学习 目录 [如何快速的开发一个完整的iOS直播app](原理篇) [如何快速的开发一个完整的iOS直播app](播放篇) [如何快速的开发一个完整的 ...

  6. 如何快速的开发一个完整的iOS直播app(原理篇)

    目录 [如何快速的开发一个完整的iOS直播app](原理篇) [如何快速的开发一个完整的iOS直播app](播放篇) [如何快速的开发一个完整的iOS直播app](采集篇) 前言 大半年没写博客了,但 ...

  7. axios封装

    前言 作为出入vue的小萌新,我在写请求的时候,也是毫不犹豫写了ajax,结果肯定是不行的... Vue 原本有一个官方推荐的 ajax 插件 vue-resource,但是自从 Vue 更新到 2. ...

  8. php怎么做网站?如何用PHP开发一个完整的网站?

    1.PHPer应具备的知识 (1)PHP知识: 熟练掌握基础函数,PHP语句(条件.循环),数组(排序.读取),函数(内部 构造),运算(数学 逻辑),面向对象(继承 接口 封装 多态静态属性)等. ...

  9. Kubernetes — 从0到1:搭建一个完整的Kubernetes集群

    准备工作 首先,准备机器.最直接的办法,自然是到公有云上申请几个虚拟机.当然,如果条件允许的话,拿几台本地的物理服务器来组集群是最好不过了.这些机器只要满足如下几个条件即可: 满足安装 Docker ...

随机推荐

  1. 创建调用Consul的客户端项目

    创建调用Consul的客户端项目 创建项目 源码 Github仓库:https://github.com/sunweisheng/spring-cloud-example

  2. 2019-4-8 zookeeper学习笔记

    zookeeper学习 ZooKeeper集合中的节点 让我们分析在ZooKeeper集合中拥有不同数量的节点的效果. 如果我们有单个节点,则当该节点故障时,ZooKeeper集合将故障.它有助于“单 ...

  3. go module管理依赖包

    go mod 最大的好处就是摆脱了GOPATH这个限制,在除了GOPATH以外的目录下也能开展你的项目 go mod使用: 1,确保你的go版本是1.1以上 2,创建一个项目目录example,并添加 ...

  4. Ansible@一个高效的配置管理工具--Ansible configure management--翻译(三)

    未经书面许可.请勿转载 一张图简单概括 Simple Playbooks Ansible is useful as a command-line tool for making small chang ...

  5. 华为要卖5G技术,虽然我和华为没有一点关系,但是我也很呵呵

    http://www.sohu.com/a/340555529_166680 老任头,竟然说出了这样的话,要卖5G技术给西方,然后塑造对手. 按照老任头的脾气,老任头应该不至于胡说八道这样的话,但是呢 ...

  6. Python基础篇(set集合)

    Python基础篇(set集合,深浅拷贝) set集合是Python的一个基本类型,一般是不常用.set中的元素是不重复的.无序的里边 的元素必须是可hash的比如int,str,tuple,bool ...

  7. 2018-2-13-win10-uwp-从-Unity-创建

    title author date CreateTime categories win10 uwp 从 Unity 创建 lindexi 2018-2-13 17:23:3 +0800 2018-2- ...

  8. 自动化运维工具ansible简单介绍

    ansible架构图 ansible安装(centos7环境下) yum update yum install ansible 验证ansible是否成功安装 ansible --version an ...

  9. Tomcat8.0源码编译

    最近打算开始研究一下Tomcat的工作原理,拜读一下源码.所以先从编译源码开始了.尽管网上有那么多的资料,但是总是觉得,自己研究一遍,写一遍,在动手做一遍能够让我们更加深入的了解.现在整个社会都流行着 ...

  10. 工具类Collections、Arrays(传入的是数组)

    Collections类: 1. Collections.sort(list)   //对list集合进行排序前提是 list里面存储的对象已经实现了 comparable接口 2. Collecti ...