Vue Axios封装 和 跨域问题

Vue Axios封装和跨域问题

封装 Axios

封装 Axios 对象

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

安装

npm install axios

1、 首先在项目 src 文件夹下创建 utils 目录,在其下创建 request.js 文件。

在这里插入图片描述
在这个文件里面,我们就导入封装的 Axios 对象。

具体怎么封装,可以看一下这个文档:
https://github.com/axios/axios#creating-an-instance

2、在 request.js 文件中引入 axios ,并且创建一个 axios 对象。

// 首先导入 axios
import axios from 'axios'

// 自己创建一个axios对象
const request = axios.create({
    
    
    baseURL: '/',   // 基础路径,默认是/ ,如果改了,会自动添加到你请求url前面
    timeout: 5000   // 请求超时,5000毫秒
})

然后导出自定义创建的axios对象。

export default request  // 导出自定义创建的 axios 对象

3、还可以在里面定义拦截器。

// 请求拦截器
request.interceptors.request.use( config => {
    
    
    // 在发送请求之前做些什么
    return config;
  }, function (error) {
    
    
    // 处理请求错误
    return Promise.reject(error);
  });

// 相应拦截器
request.interceptors.response.use( response => {
    
    
    // 在2xx范围内的任何状态代码都会触发此功能
    // 处理响应数据
    return response;
  }, function (error) {
    
    
    // 任何超出2xx范围的状态代码都会触发此功能
    // 处理响应错误
    return Promise.reject(error);
  });

到此为止 request.js 整体代码

// 首先导入 axios
import axios from 'axios'

// 自己创建一个axios对象
const request = axios.create({
    
    
    baseURL: '/',   // 基础路径,默认是/ ,如果改了,会自动添加到你请求url前面
    timeout: 5000   // 请求超时,5000毫秒
})

// 请求拦截器
request.interceptors.request.use( config => {
    
    
    // 在发送请求之前做些什么
    return config;
  }, function (error) {
    
    
    // 处理请求错误
    return Promise.reject(error);
  });

// 相应拦截器
request.interceptors.response.use( response => {
    
    
    // 在2xx范围内的任何状态代码都会触发此功能
    // 处理响应数据
    return response;
  }, function (error) {
    
    
    // 任何超出2xx范围的状态代码都会触发此功能
    // 处理响应错误
    return Promise.reject(error);
  });

export default request  // 导出自定义创建的 axios 对象

使用封装的 axios 对象

我们之前封装了一个自己的 axios 对象,拦截器也写了,尽管没内容,但是你去网上搜,大部分拦截器的功能是一样的,这个都能用,后面有时间在写,现在呢,我们的使用一下上面封装的 axios 对象。

首先我们在项目 src 目录下在创建一个文件夹 api ,以后我们调接口都在 api 目录下调用,在 api 文件夹下创建一个 test.js 文件,然后在 test.js 中发送异步请求。

// 首先引入我们自定义的axios对象
import request from '@/utils/request'

// 创建一个get请求 第一种,不建议使用
// request.get('/db.json').then( rep =>{
    
    
//     console.log('--->', rep.data)
// })

// 创建一个get请求,第二种,推荐使用
request({
    
    
    methods: 'get',
    url:'/db.json'
}).then( rep =>{
    
    
    console.log('--->', rep.data)
})

现在我们测试是可以的,但是我们得把这个请求导出,给组件使用,所以把 test.js 修改一下:

// 首先引入我们自定义的axios对象
import request from '@/utils/request'

// 创建一个get请求,第二种,推荐使用
// request({
    
    
//     methods: 'get',
//     url:'/db.json'
// }).then( rep =>{
    
    
//     console.log('get--->', rep.data)
// })

// 导出对象
export default {
    
    
    getList(){
    
    
        // 把请求对象返回,提供给组件使用
        const req = request({
    
    
            methods: 'get',
            url: '/db.json'
        })
        return req
    }
}

在组件中使用:

<template>
  <div class="hello">
    <h1>我最棒</h1>
    <p v-for="(item, index) of list" :key="index">{
    
    {
    
    item.name}}</p>
  </div>
</template>

<script>
// 导入
import testApi from "@/api/test";

export default {
    
    
  name: "HelloWorld",
  created() {
    
    
    this.initData();
  },
  data(){
    
    
    return{
    
    
      list: []
    }
  },
  methods: {
    
    
    initData() {
    
    
      // 调用
      testApi.getList().then(res =>{
    
    
        console.log('组件请求返回数据---> ', res.data)
        this.list = res.data
      })
    }
  }
};
</script>

<style scoped lang="scss">
</style>

在这里插入图片描述

跨域问题

访问采用的是同源策略,是指协议、域名、端口都要相同,其中有一个不同,就会产生跨域问题,浏览器就会限制跨域访问。

跨域问题是前端开发经常遇到的问题,在什么时候会遇到跨域问题呢?首先是前后端分离项目,使用vue开发前端项目了,肯定是前后端分离,我在说一个废话,哈哈哈哈,当前端项目和后端,也就是java后台或者是php后台间,他们的IP地址不一样,或者是端口不一样,这时候就会出现跨域问题。
在这里插入图片描述

解决跨域问题

比如,前后端项目开发完成,尽管部署在同一服务器下,IP地址肯定是一样的,但是端口肯定是不一样的,比如前段端口是8888,后端端口是8001,这时候就存在跨域问题,人家不让你调用,气人不!哈哈哈哈嗝~ 更有甚者,人家前端一个服务器,后端一个服务器,哈哈哈哈哈,恐怖!

解决跨域

  1. 通过代理请求的方式解决,将 API 请求通过代理服务器请求到 API 服务器。
  2. 开发环境中,在 vue.config.js 文件中使用 devServer.proxy 选项进行代理配置,参考:https://cli.vuejs.org/zh/config/#devserver

如下配置:

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 开头的请求,都走代理
                // 目标服务器地址,代理访问:http://localhost:8001
                target: 'http://localhost:8001',
                changeOrigin: true,   // 开启代理服务器,就会给你代理转发
                pathRewrite: {
    
    
                    // /dev-api/db.json 最终会转发到 http://localhost:8001/db.json
                    '^/dev-api': '',  // 就是将请求地址中的 /dev-api 前缀替换成空的
                }
            }
        }
    },
    lintOnSave: false, // 关闭格式检查
    productionSourceMap: false, // 打包时不会生成 .map 文件,加快打包速度
}

在这里插入图片描述

在这里插入图片描述
再请求的时候加一个前缀 /dev-api
在这里插入图片描述
加了前缀之后,加入我们后期要修改前缀,案例就一个接口好修改,但是如果以后成百上千个接口,一个一个改有些许的费劲,所以我们就把前缀抽取出来,修改接口 test.js 文件内容如下:

// 首先引入我们自定义的axios对象
import request from '@/utils/request'

// 将前缀抽取出来,以后改的话就改这个地方就行
const BASE_URI = '/dev-api'

// 导出对象
export default {
    
    
    getList(){
    
    
        // 把请求对象返回,提供给组件使用
        const req = request({
    
    
            methods: 'get',
            url: BASE_URI + '/db.json'  // 拼接前缀
        })
        return req
    }
}

效果是一样的。

如果后期需要修改跨域服务器的地址,就在 在 vue.config.js 文件中使用 devServer.proxy 选项中修改地址就可以了。
在这里插入图片描述
配置完跨域需要重启服务,不然不起作用。

OK! 跨域的问题没有了,现在可以夸我啦!!!

配置不同环境 常量值

参考资料:https://cli.vuejs.org/zh/guide/mode-and-env.html

开发环境请求接口数据和生产环境请求接口数据一般是不同的,配置不同环境的目的就是因为接口的不同不至于整天批量改URL。所以为不同的环境配置不同的请求接口 URL,通过路径前的前缀进行匹配,当前只针对的是开发环境,以后如果有生产再说哈。
在这里插入图片描述

在项目根目录下创建一个文件,名字叫做 .env.development, 将开发环境的配置项配置到此文件中。
在这里插入图片描述
在此文件中配置的各个配置项,都只能在开发环境中使用。

如果在根目录下再创建一个 .env.production 文件,那么在这个文件中所有的配置项,只能在生产环境下使用。
在这里插入图片描述
注意名字千万别敲错了哈,不然不管用。

在这里插入图片描述
所以,在配置里面,要以 VUE_APP_ 开头。

那什么样的参数/变量一般需要配置呢? 首先,代理服务器的地址需要可配置,其次代理前缀需要可配置,因为代理服务器生产环境和测试环境肯定不同,而前缀也可能因为服务器的不同而有所改变。

首先在 .env.development 文件写入配置项

# 只有以 VUE_APP_ 开头的变量会被 webpack 静态嵌入到客户端侧的包中进行使用 process.env.VUE_APP_xxx。

# 目标服务接口地址,这个地址按照自己服务环境来的,添加修改后需要重启服务
VUE_APP_HT_URL = 'http://localhost:8001'  

# 开发环境前缀
VUE_APP_BASE_API = '/dev-api'

然后修改代理项

module.exports = {
    
    
    devServer: {
    
    
        port: 8002, // 端口号,如果端口号被占用,会自动提升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]: {
    
    
                // 目标服务器地址,代理访问:http://localhost:8001
                target: 'http://localhost:8001', 
                // target:  process.env.VUE_APP_HT_URL,  // 我改成这种失败了,请求500 大佬知道原因教我!!! 
                changeOrigin: true,   // 开启代理服务器,就会给你代理转发
                pathRewrite: {
    
    
                    // /dev-api/db.json 最终会转发到 http://localhost:8001/db.json
                    // '^/dev-api': '',  // 就是将请求地址中的 /dev-api 前缀替换成空的
                    ['^' + process.env.VUE_APP_BASE_API]: ''
                }
            }
        }
    },
    lintOnSave: false, // 关闭格式检查
    productionSourceMap: false, // 打包时不会生成 .map 文件,加快打包速度
}

在这里插入图片描述
之前我们在请求的时候在 test.js 文件中加了一个 BASE_URI = ‘/dev-api’ ,现在我们可以简化一下,因为在 request.js 文件创建 axios 对象的时候,有一个 baseURL ,当时我们设置的是 ‘/’ ,我们可以直接设置成 ‘/dev-api’,test.js 中就不需要设置前缀了,记得把前缀删掉!

// 自己创建一个axios对象
const request = axios.create({
    
    
    baseURL: '/dev-api',   // 基础路径,默认是/ ,如果改了,会自动添加到你请求url前面
    timeout: 5000   // 请求超时,5000毫秒
})

在这里插入图片描述

因为之前我们在 .env.development 文件定义了一个前缀,所以还可以这样改

// 自己创建一个axios对象
const request = axios.create({
    
    
    // baseURL: '/dev-api',   // 基础路径,默认是/ ,如果改了,会自动添加到你请求url前面
    baseURL: process.env.VUE_APP_BASE_API,
    timeout: 5000   // 请求超时,5000毫秒
})

效果是一样的,需要修改的时候也不需要再去找文件,直接在 .env.development 文件统一修改就可以了。

【相关代码:https://gitee.com/wjw1014/vue_learning_axios

填坑

上面说我曾经在 .env.development 文件配置了后台连接,在 vue.config.js 文件中调用不到,问题被我老弟找到了,他真是个宝藏男孩,爱死他了。

参考这篇博文:

https://www.cnblogs.com/sese/p/11905402.html

我用的是 cli 4,除了上面的步骤,还有一步很重要的:

在这里插入图片描述

配置完成,重启就可以了!完美!nice!

猜你喜欢

转载自blog.csdn.net/weixin_42776111/article/details/107874678