关于跨域问题与axios的封装

目录

跨域问题

开发环境下前端解决跨域

axios的封装

引入axios

api路径的搭建

配置拦截器

调用接口实例


跨域问题:

协议(http/https等)、域名(如www.baidu.com)、端口号(如8080)有一个不同都算跨域。
因为一个端口号只能跑一个程序,所以前后端分离代表着项目一定存在跨域问题。 

前端在开发环境时需要解决跨域问题,但是在部署到服务器之后,就需要后端来解决。

开发环境下前端解决跨域:

vue.config.js文件下,配置反向代理proxy

  devServer: {
    // host: 'localhost', // ip 本地
    // open: true, // 配置自动启动浏览器
    port: 3000, // 设置端口号
    proxy: {
      '/api': { // 接口以api开头的才用代理
        target: '服务器ip', //axiso实例里的baseURL的值(后端路径)
        changeOrigin: true,
        pathRewrite: {
          //这里理解成用‘/api’代替target里面的地址,组件中我们调接口时直接用/api代替
          // 比如我要调用'http://xxx.xxx.x.xxx:8080/login',直接写‘/api/user/add’即可 代理后地址栏显示/  
          '^/api': '',
        }
      }
    },
  },

changeOrigin:true指是否改变域名:在本地会创建一个虚拟服务端,在这里发送并接收请求数据,这样数据交互就不会有跨域问题。实际上这个东西作用不大,感兴趣的话可以百度了解一下。https://blog.csdn.net/Old_Soldier/article/details/127204618

pathRewrite:路径重写,当实际需要请求的接口路径里没有api的时候,就需要用到路径重写(后端识别的时候把api替换成空)

最后我们调用的接口基础路径就是target+pathRewrite(使用实例参考axios的封装)

axios的封装:

axios让我们对接口的使用变得很简单,但在项目中,接口数量往往会一直增加,有一些操作,比如在请求头中夹带token,需要我们在每个接口前面都进行添加,会让代码非常冗余,且难以维护。

但如果我们对axios进行封装,那我们往往只需要写一次代码,并且后期管理或维护都能变得很简便。

引入axios:

main.js引入,通过npm install axios -g安装

// axios;    //  npm install axios -g
import axios from "axios";
axios.defaults.withCredentials = true;

api路径的搭建:

src文件下,创建api/_BaseAxios文件

import axios from "axios"; // 引入axios
import AxiosInterceptors from './_AxiosInterceptors' // 引入拦截器规则

import {
    RBAC_BASE_URL, // api路径
    TIMEOUT        // 超时时长
} from '../const.js' 

let requestConfig = {
    baseURL: RBAC_BASE_URL, // 配置api路径
    timeout: TIMEOUT        // 配置超时时长
}

const baseAxios = axios.create(requestConfig); // 创建axios实例
AxiosInterceptors.setInterceptors(baseAxios);  // 使用拦截器规则

export default baseAxios;

baseURL就是接口基础路径,所以这里也可以写成baseURL:'/api',因为开发环境和生产环境里写的baseURL不一样,所以在const.js里配置以下代码会更方便。

// export const PROJECT_NAME = 'Panda';
// export const TOKEY_ATTR_NAME = 'X-Access-Token'; // TOKEN的属性名(即客户端传token到服务端,token的属性名)
// export const IS_LOGIN_NEEDED = true; // 系统是否需要登录后使用

let rbacBaseUrl; // 基础API地址
switch (process.env.NODE_ENV) {
    case "production": // 发布到服务器 npm run build
        rbacBaseUrl = '服务器ip/';
        break;
    case "development": // 本机前端开发调试 npm run serve
    default:
        rbacBaseUrl = '/api';
        break;
}
export const RBAC_BASE_URL = rbacBaseUrl;

export const TIMEOUT = 10000; // 一般请求超时时间
// export const UPLOAD_TIMEOUT = 0; // 指定文件上传请求超时的毫秒数(0 表示无超时时间)

// //文件地址
// export const uploadImgUrl = '服务器ip/';

process.env包含关于环境变量的信息。
process.env.NODE_ENV是一个用户自定义的变量,用来判断生产环境还是开发环境,一般生产环境就是production,开发环境就是development。https://blog.csdn.net/qq_31967569/article/details/116164721

配置拦截器:

最好在api路径下添加一个js文件(与_BaseAxios同级),我的命名是_AxiosInterceptors,拦截器包含request和response两部分,request用来管理接口发送请求前的处理,response处理接收后的数据。

import store from "@/store/index";

function setInterceptors(axios) {
    // 在被then()和catch()方法处理之前,把 客户端请求 拦截下来优先处理
    // api 返回的数据均为json,如果请求没有指明,则默认视为json
    axios.interceptors.request.use(config => {
        // 在发送请求之前做些什么
        if (store.state.token) {
            // 添加请求头
            config.headers['token'] = store.state.token
            config.headers['Authorization'] = store.state.token
        }
        return config;
    }, error => {
        // 对请求错误做些什么
        return Promise.reject(error);

    });

    // 在被then()和catch()方法处理之前,把 服务器返回结果 拦截下来优先处理
    axios.interceptors.response.use(response => {
        /*** 响应成功拦截器 */
        // console.log("response", response)
        return response;
    }, error => {
        return Promise.reject(error);
    });

    return axios;
}

export default {
    setInterceptors
}

调用接口实例:

添加接口文件,写接口的时候注意一下method类型是get、post还是put之类的,这个会影响参数传递的格式,data还是params。以下是常用的接口类型。

import BaseAxios from "../_BaseAxios";
import ResHelper from "../_ResponseHelper.js";

/**
 * @description 登录                   post,data
 * @param {String} account 账号
 * @param {String} password 密码
 */
function login(params) {
    return BaseAxios({
        url: `system/Login/login`,
        method: "post",
        data: {
            "account": params.account,
            "password": params.password,
        }
        // data: params,
    })
    // .then(ResHelper.handler);
}

/**
 * @description 注册                   post,params
 * @param {Integer} account 账号
 * @param {String} password 密码
 * @param {String} code 验证码
 * @param {String} mailbox 邮箱
 * @param {String} username 名字
 * @param {Integer} phoneNumber 电话号码
 */
function register(params) {
    return BaseAxios({
        url: `system/Login/register`,
        method: "post",
        params: params
    })
}

/**
 * @description 获取用户信息               get
 * @param {String} Authorization 验证信息
 */
function getUser() {
    return BaseAxios({
        url: `system/Login/user`,
        method: "get",
    })
}

/**
 * @description 获取申请列表            get,params
 * @param {Integer} pageSize 页数
 * @param {String} keyword 姓名
 */
function getApplyList(params) {
    return BaseAxios({
        url: `system/Personal/list`,
        method: "get",
        params: params,
    })
}

export default {
    login,
    register,
    getUser,
    getApplyList,
}
import BaseAxios from "../_BaseAxios";
import ResHelper from "../_ResponseHelper.js";

/**
 * @description 增加熊猫信息             post,data
 * @param {int} number 熊猫编号
 * @param {String} birth 出生日期
 * @param {String} dna DNA
 * @param {String} englishName 英文名
 * @param {String} gender 性别
 * @param {String} image 照片
 * @param {String} name 名字
 * @param {String} roostPosition 栖息地
 */
function addPanda(params) {
    return BaseAxios({
        url: `system/Panda/panda/add`,
        method: "post",
        data: params,
    })
}

/**
 * @description 修改熊猫信息             put,data
 * @param {int} number 熊猫编号
 * @param {String} birth 出生日期
 * @param {String} dna DNA
 * @param {String} englishName 英文名
 * @param {String} gender 性别
 * @param {String} image 照片
 * @param {String} name 名字
 * @param {String} roostPosition 栖息地
 */
function editPanda(params) {
    return BaseAxios({
        url: `system/Panda/panda/edit`,
        method: "put",
        data: params,
    })
}

export default {
    addPanda,
    editPanda,
}

关于_ResponseHelper文件,本来是想通过他处理获取的数据的,但由于本次项目接口code情况不一致,就放弃使用了,如果要使用可以参考以下代码:

import SysError from "../sys/SysError.js"

// 一般处理方法
function handler(res) {
    switch (res.data.code === 200) {
        case true:
            return res.data.result;
        default:
            throw new SysError(res.data.code, res.data.message, res.data.result);
    }
}

export default {
    handler
}

src/sys/SysError

class SysError extends Error {
    constructor(code, message, data) {
        super(message);
        this.code = code;
        this.data = data;
    }
}

module.exports = SysError;

最后在需要调用接口的页面引入接口文件,就可以调用了,然后就是按情况处理数据之类的,如果不知道传过来的数据是什么就log一下,看看接口返回的response是什么。

当然也可以不封装,不封装一样可以用。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
在 React 项目中使用 Axios 进行网络请求时,可能会遇到问题。出现问题的原因是浏览器的同源策略限制,即只允许同源网址(协议、名、端口号均相同)之间进行通信。如果你需要访问不同源的资源,就需要进行处理。 以下是一些处理问题的方法: 1. 使用代理 在 React 项目中,可以通过配置代理来解决问题。在 package.json 文件中添加如下代码: ``` "proxy": "http://api.example.com" ``` 这里将代理地址设置为 http://api.example.com ,当发送请求时,axios 会自动将请求发送到代理地址,然后再由代理地址转发到目标地址。这样就可以避免问题。 2. 后端设置 CORS 如果你无法使用代理,或者代理无法满足你的需求,可以让后端设置 CORS(资源共享)来解决问题。CORS 是一种机制,它允许 Web 应用程序从不同的源访问其资源。 在后端代码中,可以添加如下代码来设置 CORS: ``` res.setHeader('Access-Control-Allow-Origin', '*'); ``` 这里将 Access-Control-Allow-Origin 设置为 * ,表示允许所有来源访问资源。当然,你也可以设置为特定的来源。 3. 使用 JSONP JSONP 是一种解决问题的方法,它利用了 HTML 中 script 标签可以加载资源的特性。在 React 项目中,可以通过使用 jsonp 库来实现 JSONP 请求。 以下是一个使用 jsonp 库的例子: ``` import jsonp from 'jsonp'; jsonp('http://api.example.com', {}, (err, data) => { if (err) { console.error(err); } else { console.log(data); } }); ``` 这里调用了 jsonp 函数,将目标地址设置为 http://api.example.com 。jsonp 函数会自动创建一个 script 标签,加载目标地址,并在加载完成后执行回调函数。 在 React 项目中使用 Axios 进行网络请求时,可以通过对 Axios 进行封装来简化代码,并提高代码的复用性。以下是一个简单的 Axios 封装示例: ``` import axios from 'axios'; const instance = axios.create({ baseURL: 'http://api.example.com', timeout: 5000, }); instance.interceptors.request.use( (config) => { // 在请求发送之前做一些处理 return config; }, (error) => { // 对请求错误做一些处理 return Promise.reject(error); } ); instance.interceptors.response.use( (response) => { // 对响应数据做一些处理 return response.data; }, (error) => { // 对响应错误做一些处理 return Promise.reject(error); } ); export default instance; ``` 这里创建了一个 Axios 实例,并设置了 baseURL 和 timeout 。然后,通过拦截器对请求和响应进行处理,并最终返回处理后的数据。在其他代码中,只需要引入封装后的 Axios 实例即可进行网络请求。 ``` import axios from './axios'; axios.get('/users').then((data) => { console.log(data); }); ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值