zl程序教程

您现在的位置是:首页 >  云平台

当前栏目

<前端人自己的跨域>React-ajax以及setupProxy配置代理

2023-09-27 14:26:51 时间

前言

😎😎欢迎来到我的博客😎😎
📔博主是一名大学在读本科生,主要学习方向是前端😊。
🍭目前已经更新了【Vue】、【React–从基础到实战】、【TypeScript】等等系列专栏🤩
🛠目前正在学习的是🔥 R e a c t 框架 React框架 React框架🔥,中间夹杂了一些基础知识的回顾⌨️
🌈博客主页👉codeMak1r.的博客
➕关注👍点赞📂收藏


本文被专栏【React–从基础到实战】收录

🕹坚持创作✏️,一起学习📖,码出未来👨🏻‍💻!

🤩react_axios

安装axios

yarn add axios

npm install axios

cnpm install axios

输入命令后,可以在package.json文件中查看是否安装完成

在这里插入图片描述

如图出现axios:版本号,代表安装完成,可以使用~

🤩在react中使用axios

例如,我们需要点击按钮向服务器发送请求:

在这里插入图片描述

首先我们需要使用 node + express搭建一个服务器

server1.js

const express = require('express');

const app = express()

app.use((request, response, next) => {
  console.log('有人请求服务器1了');
  next()
})

app.all('/students', (request, response) => {
  const students = [
    { id: '001', name: 'tom', age: 18 },
    { id: '002', name: 'jerry', age: 19 },
    { id: '003', name: 'tony', age: 20 },
  ]

  response.send(students)
})

app.listen(5000, (err) => {
  if (!err) console.log('服务器1启动,已经监听到5000端口...')
})

就像这样,服务器搭建好了,并且服务一旦开启就会被use中间件监听到,打印出“有人请求服务器1了”;

开启服务:node server1.js(或者nodemon server1.js

服务器开启在5000端口…

由于浏览器地址栏默认发送的就是get请求,我们可以在地址栏输入:http://localhost:5000/students按下回车键,查看服务是否可以成功返回数据:

在这里插入图片描述

可以看出,服务器可以正常返回数据。

那么现在就是发送服务获取学生数据了:

App.jsx中:

import React, { Component } from 'react'
// 引入axios库
import axios from 'axios'

export default class App extends Component {

  getStudentData = () => {
    // 使用axios发送get请求
    axios.get('http://localhost:5000/students')
      .then(response => {
        console.log('成功了', response.data)
      }, error => {
        console.log('失败了', error)
      }
      )
  }

  render() {
    return (
      <div>
        <button onClick={this.getStudentData}>点我获取学生数据</button>
      </div>
    )
  }
}

尝试点击按钮获取学生数据:

在这里插入图片描述

显示存在跨域问题,这是由于同源策略,react脚手架运行在3000端口,请求在5000端口的服务器的数据,就形成了跨端口访问的问题,违背了同源策略,所以访问失败。

我们可以从跨域资源共享解决方案这篇文章中得到跨域的解决方案:

server1.js

app.all('/students', (request, response) => {
  // 设置允许跨域
  response.setHeader('Access-Control-Allow-Origin', '*')
  const students = [
    { id: '001', name: 'tom', age: 18 },
    { id: '002', name: 'jerry', age: 19 },
    { id: '003', name: 'tony', age: 20 },
  ]

在app.all中添加

// 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')

再次点击按钮获取学生数据:

在这里插入图片描述

如此可见,在服务器中设置跨域是被允许的,可以正常发送ajax请求。

可是,我们作为前端开发人员,在日常开发中不能总是麻烦后端,那岂不是让人瞧不起¿??
当即振臂一呼:我们也要搞自己的跨域!

先把服务器的跨域给他删了:

response.setHeader(‘Access-Control-Allow-Origin’, ‘*’)

并且内心高呼:去nmd。

跨域?我们前端也可以!!

但是我们react脚手架运行在3000端口,服务器的数据躺在5000端口,隔江相望,望尘莫及…
我们先来看看我们的请求到底是【发送到了但是不给返回数据】还是【压根没发送到服务器】?

还是点击按钮发送数据:

我们发现,

在这里插入图片描述

说明请求已经发送到服务器了,但是由于同源策略的限制,服务器返回的数据被浏览器拦截下来了

浏览器:“ 5000端口的数据你3000端口跟着瞎参和啥,不给不给!

也就是【发送到了但是不给返回数据】…

那咋整呢?我找他5000,他不给我3000办事儿?摊给你掀了!(不是)

不给办事儿还不简单?找黄牛啊~

于是乎,我们可以找一个黄牛,叫做【代理】。

package.json中配置代理:

"proxy": "http://localhost:5000"

说明:

  1. 优点:配置简单,前端请求资源时可以不加任何前缀。
  2. 缺点:不能配置多个代理。
  3. 工作方式:上述方式配置代理,当请求了3000不存在的资源时,那么该请求会转发给5000 (优先匹配前端资源)

在这里插入图片描述

仅需一行代码,黄牛请过来了,重启脚手架来看看行不行吧:

在这里插入图片描述

一瞅成功了,黄牛果然有用~

好了,总结一下吧:

react中的axios的使用:

axios.get('http://localhost:5000/students')
      .then(response => {
        console.log('成功了', response.data)
      }, error => {
        console.log('失败了', error)
      }
      )

【分割线】

设置响应头方式允许跨域(server服务端):

response.setHeader('Access-Control-Allow-Origin', '*')

代理方式设置跨域:

// 在package.json中
"proxy": "http://localhost:5000"

⚠️但是

⚠️但是

⚠️但是

问题又来了,如果react项目需要发起多个请求,比如:我需要向5000端口的那个服务器发送请求,我还需要向5001端口的服务器发送请求,那怎么办呢?

server2.js(5001端口)

const express = require('express');

const app = express()

app.use((request, response, next) => {
  console.log('有人请求服务器2了');
  next()
})

app.all('/cars', (request, response) => {
  const cars = [
    { id: '001', name: '奔驰', price: 199 },
    { id: '002', name: '马自达', price: 109 },
    { id: '003', name: '捷达', price: 120 },
  ]

  response.send(cars)
})

app.listen(5001, (err) => {
  if (!err) console.log('服务器2启动,已经监听到5001端口...')
})

涉及到多个代理,这就需要使用到代理配置文件:setupProxy了。

🤩setupProxy.js配置跨域

注意⚠️:在setupProxy中,不能使用ES6语法,而需要使用CommonJS语法;

(CommonJS是前端模块化的一种规范,ES6是另外一种。)

这是因为,react监测到setupProxy这个文件之后,会将其加入到webpack配置之中使其生效,

而webpack配置使用的都是node中的语法(都是CommonJS)。

  1. 第一步:创建代理配置文件

    在src下创建配置文件:src/setupProxy.js
    

    下载http-proxy-middleware

    sudo npm install http-proxy-middleware   // MAC
    npm install http-proxy-middleware   // Windows
    
  2. 编写setupProxy.js配置具体代理规则:

    const { createProxyMiddleware } = require('http-proxy-middleware')
    
    module.exports = function (app) {
      app.use(
        createProxyMiddleware('/api1', { // 遇见‘/api1’这个前缀的请求,就会触发这个代理
          target: 'http://127.0.0.1:5000',  // 请求转发的目标(target)地址
          changeOrigin: true,  // 默认值为false,控制服务器收到的请求头中Host字段的值
          /*
          	changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
          	changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:3000
          	changeOrigin默认值为false,但我们一般将changeOrigin值设为true
          */
          pathRewrite: { '^/api1': '' }  
          //去除请求前缀,保证交给后台服务器的是正常请求地址(必须配置)
        }),
        createProxyMiddleware('/api2', {
          target: 'http://127.0.0.1:5001',
          changeOrigin: true,
          pathRewrite: { '^/api2': '' }
        })
      )
    }
    

对changeOrigin属性的详细说明:

changeOrigin默认值为false:若为false时,服务器可以知道请求具体是来自3000端口的;

在这里插入图片描述

changeOrigin设置为true:可以“欺骗服务器”,服务器就会以为请求来自自己的5000端口,就会放行。

在这里插入图片描述

说明:

  1. 优点:可以配置多个代理,可以灵活的控制请求是否走代理。
  2. 缺点:配置繁琐,前端请求资源时必须加前缀。

如此一来,我们只需要在发送请求的url中添加【/前缀】就可以使用代理发送请求了:

获取学生数据

getStudentData = () => {
    axios.get('/api1/students')
      .then(response => {
        console.log('成功了', response.data)
      }, error => {
        console.log('失败了', error)
      }
      )
  }

获取汽车数据

getCarData = () => {
    axios.get('/api2/cars')
      .then(response => {
        console.log('成功了', response.data)
      }, error => {
        console.log('失败了', error)
      }
      )
  }

🎉🎉如果觉得博主的文章还不错的话
➕关注博主👍点赞文章📁收藏文章
✏️原创不易你的支持将会是我最大的动力💪
🧸感谢观看