vue3项目跨域请求

1. 本地运行后端项目:http://localhost:8080

vite.config.ts

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

// https://vite.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src')
    }
  },
  base: '/',
  server: {
    // 端口号
    port: 3000,
    // 监听所有地址
    host: '0.0.0.0',
    // 服务启动时是否自动打开浏览器
    open: true,
    // 允许跨域
    cors: true,
    // 自定义代理规则
    proxy: {
      // 完整写法
      '/api': {
        target: 'http://localhost:8080', // 后端接口地址
        changeOrigin: true,
        rewrite: path => path.replace(/^\/api/, '')
      }
    }
  }
})

 .env 设置HTTP请求默认地址:前端项目地址 + '/api'

VITE_BASE_URL=http://localhost:3000/api/

 2. PostMan Mock Server:https://your-key.mock.pstmn.io

PostMan:https://identity.getpostman.com/login

vite.config.ts

  proxy: {
      // 完整写法
      '/api': {
        target: 'https://your-key.mock.pstmn.io',
        changeOrigin: true,
        rewrite: path => path.replace(/^\/api/, '')
      }
    }

.env

VITE_BASE_URL=https://your-key.mock.pstmn.io

自行封装 http.ts 设置config的baseURL

// axios配置
const config = {
  baseURL: import.meta.env.VITE_BASE_URL, // 本地测试地址
  //   withCredentials: true, // 确保发送 cookies
  timeout: 5000 // request timeout
}

http.ts 完整版

/** 封装axios **/
import axios from 'axios'
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import { message, Modal } from 'ant-design-vue'
import { getToken } from './auth'
import { useAuthStore } from '@/stores/auth'
import { createVNode } from 'vue'
import { ExclamationCircleOutlined } from '@ant-design/icons-vue'

// axios配置
const config = {
  // baseURL: '/server-address/', // 发布地址
  baseURL: import.meta.env.VITE_BASE_URL, // 本地测试地址
  //   withCredentials: true, // 确保发送 cookies
  timeout: 5000 // request timeout
}

// 定义返回值类型
export interface Result<T = any> {
  code: number
  msg: string
  data: T
}

// axios封装
class Http {
  // 定义一个axios的实例
  private instance: AxiosInstance

  // 构造函数:初始化
  constructor(config: AxiosRequestConfig) {
    // 创建axios实例
    this.instance = axios.create(config)
    // 配置拦截器
    this.interceptors()
  }

  // 拦截器:处理请求发送和请求返回的数据
  private interceptors() {
    // 请求发送之前的处理
    this.instance.interceptors.request.use(
      config => {
        console.log(`==== ${config.url} ====`)
        console.log(config.data)
        // 修改headers的Content-Type
        config.headers!['Content-Type'] = 'application/json'
        /** 在请求头部添加token **/
        let token = getToken() // 从cookies/sessionStorage里获取
        if (token) {
          // 添加token到头部
          config.headers!['Authorization'] = token
        }
        return config
      },
      error => {
        error.data = {}
        error.data.msg = '服务器异常,请联系管理员!'
        return error
      }
    )

    // 请求返回数据的处理
    this.instance.interceptors.response.use(
      (response: AxiosResponse) => {
        const { data } = response
        // 数据不解密
        const res = data
        console.log(res) // res: { code: 200, data: null, msg: '请求成功' }

        if (res.code === 200) {
          return res.data
        } else if (res.code === 204) {
          // token过期 |无效
          Modal.warning({
            title: '提示',
            icon: createVNode(ExclamationCircleOutlined),
            content: '当前用户登录已超时,请重新登录!',
            onOk() {
              // console.log('ok')
              const authStore = useAuthStore()
              authStore.logout() // 执行退出
            }
          })
        } else {
          message.error(res.msg || '服务器出错!')
          return Promise.reject(new Error(res.msg || '服务器出错!'))
        }
      },
      error => {
        console.log('进入错误')
        error.data = {}
        if (error && error.response) {
          switch (error.response.status) {
            case 400:
              error.data.msg = '错误请求'
              break
            case 500:
              error.data.msg = '服务器内部错误'
              break
            case 404:
              error.data.msg = '请求未找到'
              break
            default:
              error.data.msg = `连接错误${error.response.status}`
              break
          }
          message.error(error.data.msg || '服务器连接出错!')
        } else {
          error.data.msg = '连接到服务器失败!'
          message.error(error.data.msg)
        }
        return Promise.reject(error)
      }
    )
  }

  /** RestFul api封装 **/
  // Get请求:注意这里params被解构了,后端获取参数的时候直接取字段名
  get<T = Result>(url: string, params?: object): Promise<T> {
    return this.instance.get(url, { params })
  }

  // Post请求
  post<T = Result>(url: string, data?: object): Promise<T> {
    return this.instance.post(url, data)
  }

  // Put请求
  put<T = Result>(url: string, data?: object): Promise<T> {
    return this.instance.put(url, data)
  }

  // DELETE请求
  delete<T = Result>(url: string): Promise<T> {
    return this.instance.delete(url)
  }
}
export default new Http(config)

/api/auth.ts

import http from '@/utils/http'
import type { LoginRequest, LoginResponse } from '@/types'

/** 用户登录
 * @param username
 * @param password
 * **/
export const loginCheck = (params: LoginRequest): Promise<LoginResponse> => {
  return http.post('/login', params)
}

// 测试接口-204token过期
export const testYY = (): Promise<null> => {
  return http.post('/yy/test')
}
Vue 3项目中解决问题,可以通过以下几种方式: 1. **代理配置**:在Vue 3项目中,通常使用Vite或Webpack作为构建工具。对于Vite,可以在`vite.config.js`中配置代理(proxy),对于Webpack,可以在`webpack.config.js`中配置`devServer`的`proxy`选项。代理可以帮助转发请求到指定的后端服务器,从而绕过浏览器的同源策略限制。 示例配置(Vite): ```javascript // vite.config.js import { defineConfig } from &#39;vite&#39;; import vue from &#39;@vitejs/plugin-vue&#39;; // https://vitejs.dev/config/ export default defineConfig({ plugins: [vue()], server: { proxy: { &#39;/api&#39;: { target: &#39;http://backend.example.com&#39;, changeOrigin: true, rewrite: path => path.replace(/^\/api/, &#39;&#39;) } } } }); ``` 2. **后端设置CORS**:如果你控制后端服务,可以通过设置CORS(源资源共享)响应头来允许请求。在后端代码中设置`Access-Control-Allow-Origin`头部,指定允许访问的名。 示例(Node.js): ```javascript const express = require(&#39;express&#39;); const app = express(); app.use(function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); next(); }); app.listen(3000, function() { console.log(&#39;CORS-enabled web server listening on port 3000&#39;); }); ``` 3. **前端配置**:如果使用Axios作为HTTP请求库,可以在创建Axios实例时配置`withCredentials`属性为`true`,并确保请求头中包含`credentials`。这适用于CORS允许携带凭证的场景。 示例配置(Axios): ```javascript import axios from &#39;axios&#39;; const instance = axios.create({ baseURL: &#39;http://backend.example.com/api&#39;, withCredentials: true, }); instance.interceptors.request.use(function (config) { // 在发送请求之前做些什么 return config; }, function (error) { // 对请求错误做些什么 return Promise.reject(error); }); export default instance; ``` 4. **环境变量**:在开发环境下,可以使用环境变量`.env`来配置代理,或者临时允许,但在生产环境中应当小心使用,确保安全。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值