Vue3全局配置Axios并解决跨域请求问题示例详解

背景

对于前后端分离项目,前端和后端端口不能重复,否则会导致前端或者后端服务起不来。例如前端访问地址为: http://localhost:8080/ ,后端访问地址为 http://localhost:8081/ 。后端写好Controller,当用Axios访问该接口时,将会报错:

Access to XMLHttpRequest at ' http://localhost:8081/login ' from origin ' http://localhost:8080 ' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

本文内容从axios部署开始到解决跨域问题。

前端: Vue3;Axios 1.6.0 ;Element-Plus
后端:Springboot 2.7.14

这里提供两种解决方案,都是基于后端跨域访问的配置,前端不作任何允许跨域访问的设置,因为试过无效。

一、部署Axios

Axios的基本介绍:
(1)axios 是一个基于promise的HTTP库,支持promise所有的API
(2)浏览器端/node端(服务器端)都可以使用,浏览器中创建XMLHttpRequests
(3)支持请求/响应拦截器
(4)它可以转换请求数据和响应数据,并对响应回来的内容自动转换成 JSON类型的数据
(5)批量发送多个请求
(6)安全性更高,客户端支持防御XSRF

1. npm 安装 axios

npm install axios

2. 创建 request.ts,创建axios实例

在项目根目录下,也就是src目录下创建文件夹api/,并创建request.js ,该js用于创建axios实例。

import axios from 'axios';
import { ElMessage } from 'element-plus';
import { v4 as uuidv4 } from "uuid";

//ts使用
import { Md5 } from "ts-md5";


// 创建axios实例
const $http = axios.create({
  // 请求的域名,基本地址,proxy 代理时会将“/api”以及前置字符串会被替换为真正域名
   baseURL: '/api',
  // 跨域请求时发送Cookie
  withCredentials: true, // 视情况而定
  // 超时时间
  timeout: 5000,
  headers: {
    // 设置后端需要的传参类型
    'content-type': 'application/json; charset=utf-8',
    // "Lux-mateApiNonce": uuid, //每次调取接口生成的uuid
    // "Lux-mateApiSignature": mateApi, //md5(method+requestURI+nonce+timestamp+appId+appSecret)
    // "Lux-mateApiTimestamp": timestamp, // 每次调取接口的时间戳(秒级)
  }, 
});

// 请求拦截器
$http.interceptors.request.use((config) => {
    // 获取当前时间戳
    const timestamp = parseInt(Date.now() / 1000);
    const uuid =  uuidv4(); // 生成UUID
    console.log(parseInt(Date.now() / 1000),'3333333')
    // console.log(config.method)
    let signStr =config.method + config.url + uuid + timestamp + "Herdsric" + "Herdsric2024"
    console.log('验签',signStr)
    let mateApi = Md5.hashStr(signStr.toUpperCase());
    console.log(mateApi)
    config.headers['Lux-mateApiSignature'] = mateApi
    config.headers['Lux-mateApiNonce'] = uuid //每次调取接口生成的uuid
    config.headers['Lux-mateApiTimestamp'] = timestamp// 每次调取接口的时间戳(秒级)
    config.headers = config.headers || {};
    // if (localStorage.getItem("token")) {
    //     config.headers.token = localStorage.getItem("token") || "";
    // }
    return config;
  });
  
  // 响应拦截器
  $http.interceptors.response.use((response) => {
    return response;
  }, (error) => {
    ResponseProcessing(error);
  });
  
  /**
   * 响应处理
   * @param error 
   * @returns 
   */
  const ResponseProcessing = (error: { response: { state: any; data: any; }; }) => {
    if (error.response) {
      switch (error.response.state) {
        case 401:
          ElMessage.warning("资源没有访问权限!");
          break;
        case 404:
          ElMessage.warning("接口不存在,请检查接口地址是否正确!");
          break;
        case 500:
          ElMessage.warning("内部服务器错误,请联系系统管理员!");
          break;
        default:
          return Promise.reject(error.response.data); // 返回接口返回的错误信息
      }
    } else {
        ElMessage.error("遇到跨域错误,请设置代理或者修改后端允许跨域访问!");
    }
  };
  
  export default $http;

在这里,我们自定义axois实例化对象,配置了默认的访问i后端ip和端口等,并在末尾使用export 导出api配置,便于在其他单文件中引入 request.ts.

3. 在main.ts中全局注册axios

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'


const app = createApp(App)
app.use(ElementPlus)
app.use(router)
app.mount('#app')
// createApp(App).use(router).mount('#app')

4. 创建api.ts文件夹

import $http from './Interceptor';

export function getTestData(params: any) {
    return $http({
      url: '/',
      method: 'get',
      params
    })
  }

4. 在页面中使用axios

import { getTestData } from "../http/API";
const fetchUserData = async () => {
  try {
    let params = {
      
    };
    const response = await getTestData(params);
    if (response.data.code == 0) {
     
    } else {
     
    }
  } catch (error) {
    ElMessage.error("网络异常,请稍后再试");
    console.error("There was an error fetching the data:", error);
  }
};

4. 解决跨域问题。vite.config.ts

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// import path from 'path';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
    // 解决跨域问题
  server: {
    host: '0.0.0.0',
    // port: 4000,
    proxy: {
      '/api': {
        target: 'http://192.168.31.17:4000',
        // secure: false, // 请求是否为https
        changeOrigin: true,
        rewrite:(path)=>path.replace(/^\/api/,'') //api替换为'',
      },
    },
  },



  // resolve: {
  //   alias: {
  //     '@': path.resolve(__dirname, 'src'),
  //   },
  // },
  css: {
    preprocessorOptions: {
      less: {
        additionalData: `@import "@/assets/style/base.less";`,
      }
    },
  },
})

  • 24
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值