美文网首页
vue - axios封装

vue - axios封装

作者: w_wx_x | 来源:发表于2019-12-18 20:44 被阅读0次
1.安装axios
npm i axios
环境配置.png
.env.development.png
.env.production.png
.env.test.png
package.json.png
2.新建一个axios.js文件,对axios进行封装
import axios from 'axios'
import QS from 'qs' // 引入qs模块,用来序列化post类型的数据
import jsonBig from 'json-bigint' // 解决后端返回大数字问题(控制台中preview和response值不同)
import store from '@/store/index' // 导入vuex,因为我们要使用到里面的状态对象
import { Message, Loading } from 'element-ui'; 

// 请求加载
let loading:any
let needLoadingRequestCount = 0
function showLoading () {
    if(needLoadingRequestCount === 0) {
        loading = Loading.service({
            lock: true,
            text: '加载中...',
            background: 'rgba(0,0,0,0.2)'
        })
    }
}
function hideLoading () {    
    if(needLoadingRequestCount <= 0) return
    needLoadingRequestCount--
    if(needLoadingRequestCount === 0) {
        loading.close()
    }
}

// axios基本配置信息:baseURL、设置请求超时、请求头设置
const instance = axios.create({
  baseURL: process.env.VUE_APP_DATA_URL,
  timeout: 10000,  // 若为0表示无超时时间
  headers: {
      'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
  },
  // `transformResponse` 在传递给 then/catch 前,允许修改响应数据
  transformResponse: [function (data) {
        try {
            // 如果转换成功则返回转换的数据结果
            return jsonBig.parse(data)
        } catch (err) {
            // 如果转换失败,则包装为统一数据格式并返回
            return {
                data
            }
        }
    }]
})

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

// 提示函数
const tip = msg => {
    Message({
        icon: 'warning',
        message:msg
    })
}

// 请求拦截
instance.interceptors.request.use(
    config => {
        /*
            每次发送请求之前判断vuex中是否存在token
            若存在,统一在http请求的header上都加上token,后台根据token判断你的登录情况
            即使本地存在token也有可能是过期的
            所以在响应拦截器中对返回状态进行判断
            token
                一般登录完成,将用户的token通过localstorage或cookie存在本地
                用户在每次进入页面的时候,先从本地存储中读取token
                若token存在则说明用户已经登录过,更新vuex中的token状态
                每次请求接口的时候,请求头中携带token,后台判断携带的token是否过期
                若未携带,则说明没有登录过
        */
        showLoading()
        const token = store.state.token
        token && (config.headers.Authorization = token)
        return config
    },
    error => {
        hideLoading()
        return Promise.error(error)
    }
)

// 响应拦截:服务器返回给我们的数据,进行统一的处理
instance.interceptors.response.use(
    response => {
        hideLoading()
        if(response.status === 200){
            return Promise.resolve(response)
        } else {
            return Promise.reject(response)
        }
    },
    /*
        以下是服务器状态码不是2开头的情况,和后台人员协商好统一的错误状态码
    */
    error => {
        hideLoading()
        if (error.response.status) {
            switch (error.response.status){
                // 401未登录,携带当前页面路径跳转至登录页面,登录成功跳转至当前页
                case 401:
                    toLogin()
                    break;         
                // 403 token过期,对用户进行过期提示,清除本地token和vuex的token对象,跳转至登录页
                case 403:
                    tip('登录过期,请重新登录')
                    localStorage.removeItem('token');
                    store.commit('loginSuccess', null);
                    setTimeout(() => {                        
                        toLogin()                   
                    }, 1000);                    
                    break; 
                // 404请求不存在
                case 404:
                    tip('网络请求不存在')
                    break;
                // 其他错误,直接抛出错误提示
                default:
                    tip(error.response.data.message)
            }
            return Promise.reject(error.response)
        }
    }    
)

// get方法的封装(url-请求的地址,params-请求的参数)
export function get(url,params){
    return new Promise((resolve,reject)=>{
        instance.get(url,{
            params:params
        }).then(res => {
            resolve(res.data)
        }).catch(err => {
            reject(err.data)
        })
    })
}

// post方法的封装(url-请求的地址,params-请求的参数)
export function post(url,params){
    return new Promise((resolve,reject)=>{
        instance.post(url,QS.stringify(params)).then(res => {
            resolve(res.data)
        }).catch(err => {
            reject(err.data)
        })
    })
}
3.api.js(api的统一管理,模块化)
// address.js
import { get, post } from './axios.js'
const address = {
    // 如一个post请求的接口,url: http://www.baiodu.com/api/v1/users/my_address/address_edit_before
    apiAddress(p){
        return post('api/v1/users/my_address/address_edit_before', p)
    },
    apiAddressDetail(p){
        return post('api/v1/users/my_address/address_detail', p)
    }
}
export default address



// index.js
import address from 'api/address.js'
import article from 'api/article.js'
...// 其它模块的接口

export default {
    address,
    article
}



// main.js
import Vue from 'vue'
import App from './App'
import router from './router' // 导入路由文件
import store from './store' // 导入vuex文件
import api from './api/index' // 导入api接口

Vue.prototype.$api = api    // api挂载到vue原型上
4.封装好的接口调用
export default{
    name:'',
    created(){
        this.onLoad()    
    },
    methods:{
        onLoad(){
            this.$api.address.apiAddress({
                type:0,sort:1
            }).then(
                res=>{
                    // 获取数据成功的其它操作
                }
            )
        }
    }
}

相关文章

网友评论

      本文标题:vue - axios封装

      本文链接:https://www.haomeiwen.com/subject/uoxpnctx.html