推荐使用Vue-cli工具来创建和管理项目,就算刚开始不熟悉,用着用着便可知晓其中的奥妙。前一段时间官方所推荐的数据请求插件还是Vue-resource,但现在已经变了,变成了Axios,不用知道为什么变了,反正这个用起来比那个好一些,用就是了,下面是一些封装axios请求的一些经验,不对之处,还望多多指教!

01

创建文件,Vue项目初始化之后,在src目录下再创建一个util工具文件夹,一般就是用来存放一些封装的函数方法,现在让我们在util文件目录下创建一个http.js文件,封装axios方法。

02

直接上代码(常规版),代码中有详细的注释

import axios from 'axios' //引用axios
import {Promise} from 'es6-promise'   //引入Promise

// axios 配置
axios.defaults.timeout = 5000;  //设置超时时间
axios.defaults.baseURL = 'http://localhost:4000/api/v1/'; //这是调用数据接口

// http request 拦截器(所有发送的请求都要从这儿过一次),通过这个,我们就可以把token传到后台,我这里是使用sessionStorage来存储token等权限信息和用户信息,若要使用cookie可以自己封装一个函数并import便可使用
axios.interceptors.request.use(
    config => {
        const token = sessionStorage.getItem("token"); //获取存储在本地的token
        config.data = JSON.stringify(config.data);
        config.headers = {
            'Content-Type':'application/json' //设置跨域头部,虽然很多浏览器默认都是使用json传数据,但咱要考虑IE浏览器。
        };
        if (token) {
            config.headers.Authorization = "Token " + token; //携带权限参数
        }
        return config;
    },
    err => {
        return Promise.reject(err);
    }
);


// http response 拦截器(所有接收到的请求都要从这儿过一次)
axios.interceptors.response.use(
    response => {
//response.status===401是我和后台约定的权限丢失或者权限不够返回的状态码,这个可以自己和后台约定,约定返回某个自定义字段也是可以的
        if(response.status == 401) {
            router.push({ //push后面是一个参数对象,可以携带很多参数,具体可以去vue-router上查看,例如query字段表示携带的参数
                path: '/login' 
            })
        }
        return response;
    },
    error => {
        return Promise.reject(error.response.data)
    });

export default axios;

/**
 * fetch 请求方法
 * @param url
 * @param params
 * @returns {Promise}
 */
export function fetch(url, params = {}) {

    return new Promise((resolve, reject) => {
        axios.get(url, {
            params: params
        })
        .then(response => {
            resolve(response.data);
        })
        .catch(err => {
            reject(err)
        })
    })
}

/**
 * post 请求方法
 * @param url
 * @param data
 * @returns {Promise}
 */
export function post(url, data = {}) {
    return new Promise((resolve, reject) => {
        axios.post(url, data)
            .then(response => {
                resolve(response.data);
            }, err => {
                reject(err);
            })
    })
}

/**
 * patch 方法封装
 * @param url
 * @param data
 * @returns {Promise}
 */
export function patch(url, data = {}) {
    return new Promise((resolve, reject) => {
        axios.patch(url, data)
            .then(response => {
                resolve(response.data);
            }, err => {
                reject(err);
            })
    })
}

/**
 * put 方法封装
 * @param url
 * @param data
 * @returns {Promise}
 */
export function put(url, data = {}) {
    return new Promise((resolve, reject) => {
        axios.put(url, data)
            .then(response => {
                resolve(response.data);
            }, err => {
                reject(err);
            })
    })
}

03

(动态版)axios的拦截器不是必要的,不是每个项目都需要,而且headers里面的Content-TypeAuthorization不止一种,这时就需要使用另一种方法。

util/http.js
import axios from 'axios' //引用axios
import {Promise} from 'es6-promise'   //引入Promise

// axios 配置和拦截器都不用了,这里我使用了一个动态配置数据请求地址,在App.vue中,代码在下面,这个也不是必须的。


//^_^下面都设置一个默认的头部,使用的时候可以传入数据覆盖^_^,例如使用fetch(GET)方法时,没有请求数据,但是请求头有变化,则应写成 fetch("地址", {}, {"这里写头部的内容"})   记住没数据用一个空对象占位置
/**
 * fetch 请求方法
 * @param url
 * @param params
 * @returns {Promise}
 */
export function fetch(url, params = {}, headers = {
    'Content-Type': 'application/json', //设置跨域头部
    "Authorization": 'JWT ' + sessionStorage.getItem("authToken")
}) {

    return new Promise((resolve, reject) => {
        axios.get(url, {
            params: params,
            headers: headers
        })
        .then(response => {
            resolve(response.data);
        })
        .catch(err => {
            reject(err.response)
        })
    })
}

/**
 * post 请求方法
 * @param url
 * @param data
 * @returns {Promise}
 */
export function post(url, data = {}, config = {
    "headers": {
        'Content-Type': 'application/json', //设置跨域头部
        "Authorization": 'JWT ' + sessionStorage.getItem("authToken")
    }
}) {
    return new Promise((resolve, reject) => {
        axios.post(url, data, config)
            .then(response => {
                resolve(response.data);
            }, err => {
                reject(err.response);
            })
    })
}

/**
 * patch 方法封装
 * @param url
 * @param data
 * @returns {Promise}
 */
export function patch(url, data = {}, config = {
    "headers": {
        'Content-Type': 'application/json', //设置跨域头部
        "Authorization": 'JWT ' + sessionStorage.getItem("authToken")
    }
}) {
    return new Promise((resolve, reject) => {
        axios.patch(url, data, config)
            .then(response => {
                resolve(response.data);
            }, err => {
                reject(err.response);
            })
    })
}

/**
 * put 方法封装
 * @param url
 * @param data
 * @returns {Promise}
 */
export function put(url, data = {}, config = {
    "headers": {
        'Content-Type': 'application/json', //设置跨域头部
        "Authorization": 'JWT ' + sessionStorage.getItem("authToken")
    }
}) {
    return new Promise((resolve, reject) => {
        axios.put(url, data, config)
            .then(response => {
                resolve(response.data);
            }, err => {
                reject(err.response);
            })
    })
}
App.vue(这是在src目录下的程序入口文件)
<template>
  <div id="app">
    <router-view/>
  </div>
</template>

<script>
import axios from 'axios';
let protocol = window.location.protocol; //协议
let host = window.location.host; //主机
let reg = /^localhost+/;
if(reg.test(host)) {
  //若本地项目调试使用
  axios.defaults.baseURL = 'http://10.0.xx.xxx:xxxx/api/';
} else {
  //动态请求地址
  axios.defaults.baseURL = protocol + "//" + host + "/api/";
}
axios.defaults.timeout = 30000;
export default {
  name: 'app',
  axios   //这里记得导出,若请求地址永久固定一个,则就按照`普通版`配置一个baserURL就可以了
}
</script>

<style lang="scss">  //这里我使用的是scss
@import '~@/style/style'
</style>

04

总结

  • 常见问题

    • 在使用动态版时,为什么称为动态呢,是因为访问地址和请求地址是同一个地址可端口号,例如我通过http://www.cmgos.com(默认端口80)访问项目,那么我的baseURL会自动的变为http:www.cmgos.com:80/api/,这么做的原因是当某一天项目迁移或者http改为https时,不用你再去更改请求地址,程序自动就完成了
    • 数据请求地址配置不正确?如果你配置了baseURL,那么你封装的函数在使用时仅需传入基于baseURL的请求地址,例如传入login/那么请求地址会自动变为http:www.cmgos.com:80/api/login/,若未配置,那么可以直接传入整个请求地址
  • 注意事项

    • 在使用动态版时,由于没有使用拦截器,所以下面封装的函数在返回错误的时候需要写成err.response.data来获取返回的数据,但我写的是err.response,因为这样可以拿到(status)状态码等信息,若不需要判断返回的状态码,则改为err.response.data便可
如果觉得我的文章对你有用,请随意赞赏

你可能感兴趣的文章

12 条评论
吴hr · 1月15日

好文 学习了

+1 回复

0

使用过程中有什么不懂之处,可随时私信我,大家一起探讨探讨,互相学习

luozz 作者 · 1月16日
coolfxl · 2月13日

axios.defaults.baseURL如何设置多个,
比如说:当我请求接口地址为:https://www.baidu.com/**的时候
axios.defaults.baseURL = https://www.baidu.com
当我请求接口地址为:https://segmentfault.com/*的时候
axios.defaults.baseURL = https://segmentfault.com

+1 回复

0

@coolfxl 若有多个链接地址,且链接之间没有多大关联的时候,就可以不用这样配置baseURL,虽然可以在其他地方引入并改变基础配置,但是那样容易出错,这种配置方法仅适用于主机地址一直,仅改变请求路径型的。 
这种的解决办法是不配置基础请求地址,在src目录下新建一个config目录,里面写一个api.js用于存放所有要用到的请求地址,利用export导出,在其它需要用到的地方引入就可以根据命名来取到相应的api。 关于这个api.js的具体写法若不会的话,欢迎继续留言,方便的时候会给你写一个demo参考,我现在回老家过年了,没有使用电脑,用手机不方便写代码!

luozz 作者 · 2月14日
0

非常谢谢您,方便的时候给我一个demo吧,因为我们的项目有多个模块,部署在不同的域名下,需要调用不同域名下的接口来实现,但是我动态给axios.defaults.baseURL赋值无法达到想要的效果,会出现实际要请求的url总是在下一个请求的时候才会出现,导致当前的请求地址是上一个请求的地址。您说的这个方法,我不是很懂的实现,但是您给了一个思路,很谢谢您,希望在您方便的时候能给我一个demo或者进一步的指教,先行谢过了

coolfxl · 2月14日
luozz 作者 · 2月14日

所有多个链接地址,切链接之间没有多大关联的时候,就可以不用这样配置baseURL,虽然可以在其他地方引入并改变基础配置,但是那样容易出错,这种配置方法仅适用于主机地址一直,仅改变请求路径型的。
这种的解决办法是不配置基础请求地址,在src目录下新建一个config目录,里面写一个api.js用于存放所有要用到的请求地址,利用export导出,在其它需要用到的地方引入就可以根据命名来取到相应的api。

关于这个api.js的具体写法若不会的话,欢迎继续留言,方便的时候会给你写一个demo参考,我现在回老家过年了,没有使用电脑,用手机不方便写代码!

回复

0

@luozz 手机打字不好操作,老容易打错别字!😂😂

luozz 作者 · 2月14日
0

非常谢谢您,方便的时候给我一个demo吧,因为我们的项目有多个模块,部署在不同的域名下,需要调用不同域名下的接口来实现,但是我动态给axios.defaults.baseURL赋值无法达到想要的效果,会出现实际要请求的url总是在下一个请求的时候才会出现,导致当前的请求地址是上一个请求的地址。您说的这个方法,我不是很懂的实现,但是您给了一个思路,很谢谢您,希望在您方便的时候能给我一个demo或者进一步的指教,先行谢过了

coolfxl · 2月14日
0

@coolfxl 现在回家过年了,电脑都没带,这几天过年应该不会那么忙写项目吧

luozz 作者 · 2月14日
载入中...
luozz luozz

3.9k 声望

发布于专栏

Vue2.x

密切关注Vue2.x在开发过程中遇到的问题,分享遇到的问题并提供自己的解决方法,同时向更多的人分享更多的能简化开发的操作方式。

0 人关注