Axios 封装和跨域问题

2,446 阅读5分钟

1.1 封装Axios对象

因为项目中很多组件中要通过 Axios 发送异步请求,所以封装一个 Axios 对象。自已封装的 Axios 在后续可以使用 axios 中提供的拦截器。

​ 1.在src目录下创建utils目录,在utils下创建request.js文件

​ 2.内容:

import axios from 'axios' //引入axios
 
// 手动创建一个 axios 对象, 参考: https://github.com/axios/axios#creating-an-instance 
const request = axios.create({  
    // 请求配置参考: https://github.com/axios/axios#request-config  
    // 根据不同环境设置 baseURL, 终发送请求时的URL为: baseURL + 发送请求时写URL ,  
    // 比如 get('/test'), 终发送请求是: /dev-api/test  
    // baseURL: '/dev-api',
    baseURL: '/',
    timeout: 5000 // 请求超时
})
 
export default request // 导出 axios 对象

1.2 测试封装的Axios

  1. public下创建data.json数据文件,内容如下:
[
	{"name": "小梦", "age": 18},
	{"name": "小岳岳", "age": 28},
	{"name": "林志玲", "age": 38}
]

​ 2. 在src目录下创建api目录,在api目录下创建test.js文件

​ 3. 测试请求data.json,直接请求http://localhost:8888/data.json,不用加public

// @ 代表的是 /src
// import axios from '@/utils/request'
import request from "@/utils/request";
 
const BASE_URL = 'http://localhost:8888'

// 测试1 调用get方式发送get请求
request.get(BASE_URL + "/data.json").then(response => {
    console.log("get1", response.data);
}).catch(error => {
    console.log(error);
});

// 测试2, 使用对象形式传入请求配置,如 请求url, method,param 
request({
    url: BASE_URL + "/db.json",
    method: "get"
}).then(response => {
    console.log("get2", response.data);
}).catch(error => {
    console.log(error);
});

4.导出对象方式:

​ 导出的默认对象里面是方法,方法返回值为 Promise 对象,通过它调用 then 获取响应数据

// 测试3 导出默认对象
export default {
    getList(data) {
        const req = request({
            type: "get",
            url: BASE_URL+ "/db.json",
            data:data  //传参过来的data
        });
        // console.log(req) // Promise
        return req;
    }
}

  1. 在 HelloWorld.vue中导入test.js
<script>
// 直接导入 测试1和测试2 就会执行
import testApi from '@/api/test'
//验证 测试3
export default {
    created() {
        // 钩子中初始化数据
        this.fetchData(data)
    },
    methods: {
        // data 参数的传递
   		fetchData(data) {
            // 直接调用test文件中的对象,实现数据的请求
 			testApi.getList(data).then(response => {
                console.log('get3', response.data)
            }).catch(error => {
                console.log(error)
            })
        }
    },
 
  name: "HelloWorld",
    props: {
        msg: String
    },
};
</script>

1.3 Axios跨域问题

**什么是跨域:**前后端分离时,前端和后端API服务器可能不在同一台主机上,就存在跨域问题,浏览器限制了跨域访问。(跨域只存在于PC端) 同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域。

同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域。

如下面示例存在跨域:

前端页面部署在:http://localhost:8001 即本地ip端口8001上;

后端API部署在: http://localhost:8002 即本地ip端口8002上 ; 它们IP一样,但是端口不一样,所以存在跨域问题。 跨域解决: 通过代理请求的方式解决,将 API 请求通过代理服务器请求到 API 服务器。 开发环境中,在 vue.config.js 文件中使用 devServer.proxy 选项进行代理配置。

参考:cli.vuejs.org/zh/config/#d…

1.4 解决开发环境跨域问题

1.在vue.config.js文件中使用devServer.proxy选项进行代理配置

module.exports = {
    devServer: {
        port: 8888, // 端口号,如果端口号被占用,会自动提升1
        host: "localhost", //主机名, 127.0.0.1,  真机 0.0.0.0
        https: false, //协议
        open: true, //启动服务时自动打开浏览器访问
        proxy: { //代理配置
            // 匹配 /dev-api 开头的请求,
            '/dev-api': {
                // 目标服务器, 代理访问到 https://localhost:8001
                target: 'http://localhost:8001',
                // 开启代理:在本地会创建一个虚拟服务端,然后发送请求的数据,
                // 并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
                changOrigin: true, //开启代理
                pathRewrite: {
                    // 会将 /dev-api 替换为 '',也就是 /dev-api 会移除,
                    // 如 /dev-api/db.json 代理到 https://localhost:8080/db.json
                    '^/dev-api': '',
                }
            }
        }
    },
 	lintOnSave: false, // 关闭格式检查
 	productionSourceMap: false // 打包时不会生成 .map 文件,加快打包速度
}

1.5 配置不同环境 常量值

参考:cli.vuejs.org/zh/guide/mo…

开发环境请求 Mock.js 获取数据,开发环境请求后台接口获取数据,不同环境请求的URL不一样,所以要为不同环 境匹配不同请求接口URL,通过路径前缀进行匹配。当前只针对开发环境,后面会生产部署再讲生产如何实现。

  1. 在 根目录下创建.env.development.env.production 文件
  2. .env.development 文件配置(注意开发和生产环境配置不要搞反了)
# 使用 VUE_APP_ 开头的变量会被 webpack 自动加载
# 定义请求的基础URL, 方便跨域请求时使用
VUE_APP_BASE_API = '/dev-api'
 
# 接口服务地址, 以你自已的为主
# 可更改为你自已配置的 Easy-Mock 接口服务地址
VUE_APP_SERVICE_URL = 'http://localhost:8080'
  1. .env.production 文件配置(注意开发和生产环境配置不要搞反了)
# 使用 VUE_APP_ 开头的变量会被 webpack 自动加载
# 定义请求的基础URL, 方便跨域请求时使用
VUE_APP_BASE_API = '/pro-api'
  1. 测试:在 main.js 中添加以下代码,看下浏览器控制台是否会输出

    在项目任意模块文件中,都可以使用 process.env.VUE_APP_BASE_API 获取值

console.log(process.env.VUE_APP_BASE_API)

1.6 重构代理配置

  1. 在重构 vue.config.js 中的 devServer.proxy 代理配置
module.exports = {
    devServer: {
        port: 8888, // 端口号,如果端口号被占用,会自动提升1
        host: "localhost", //主机名, 127.0.0.1,  真机 0.0.0.0
        https: false, //协议
        open: true, //启动服务时自动打开浏览器访问    
    proxy: {
  		// 匹配 /dev-api 开头的请求,
        // '/dev-api': {
        [process.env.VUE_APP_BASE_API]: {
            // 目标服务器, 代理访问到 https://localhost:8001
            // target: 'http://localhost:8001',
            target: process.env.VUE_APP_SERVICE_URL,// 在 .env.development 中配置的
            // 开启代理:在本地会创建一个虚拟服务端,然后发送请求的数据,
            // 并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
            changOrigin: true, //开启代理
            pathRewrite: {
                // 会将 /dev-api 替换为 '',也就是 /dev-api 会移除,
                // 如 /dev-api/db.json 代理到https://localhost:8080/db.json
                // '^/dev-api': '',
                ['^' + process.env.VUE_APP_BASE_API]: ''
            }
        }
    }
  },
 
  	lintOnSave: false, // 关闭格式检查
    productionSourceMap: false // 打包时不会生成 .map 文件,加快打包速度
}

2.修改 utils/request.js 文件配置: baseURL: process.env.VUE_APP_BASE_API

import axios from "axios"
// 手动创建一个 axios 对象, 参考: https://github.com/axios/axios#creating-an-instance
const request = axios.create({
    // 请求配置参考: https://github.com/axios/axios#request-config
    // 根据不同环境设置 baseURL, 终发送请求时的URL为: baseURL + 发送请求时写URL ,
    // 比如 get('/test'), 终发送请求是: /dev-api/test
    // baseURL: '/dev-api',
    // baseURL: '/',
    // 根目录下的 .env.development 与 .env.production 中配置 VUE_APP_BASE_API
    baseURL: process.env.VUE_APP_BASE_API, // "/dev-api"
    timeout: 5000 // 请求超时
})
 
export default request // 导出 axios 对象

  1. 将 test.js 中的 BASE_URL 变成空字符
const BASE_URL = ""
  1. 重启项目,再次访问