上节课我们结束了整个TodoList案例,而且也做了阶段性的总结。接下来我们将要进入到下一个环节:React ajax

回顾

  • reduce方法来着条件统计
  • defaultChecked只在第一次加载起作用
  • 要学会需求分析和功能实现思路分析
  • 某个组件使用的数据存放在自身的state
  • 某些组件使用的数据存放在共同的父组件的state
  • 父组件给子组件传递数据直接通过props
  • 子组件给父组件传递数据需要父组件提前提供一个入口函数,并通过props将入口函数传给子组件,由子组件调用该入口函数

以上便是TodoList案例的主要要点

前置说明

  • react本身只关注界面,不包含发送ajax请求的代码
  • 前端通过ajax请求与后台交互(json数据)
  • react应用中需要集成第三方ajax库(或者自己封装)

常用的ajax请求库

  • jQuery:比较重量级,而且直接操作DOM,如果需要另外引入不建议使用
  • axios:轻量级,建议使用
    • 封装XmlHttpRequest对象的ajax
    • Promise风格
    • 可以用在浏览器和node服务端

安装axios

那么我们对比了jQueryaxios之后,也明确了我们更建议使用axios,那么我们来写个示例看一看吧。首先我们创建一个新的项目。然后删除掉多余的文件,准备好容器,入口文件和App组件。这是准备工作。

但是我们有项目了,脚手架里有axios吗?是不是肯定没有的啊?那么我们既然要用肯定得安装啊。然后我们在命令行里进入到这个项目中去,然后执行命令npm i axios来安装axios库。

示例

既然安装了axios,项目也有了,那么我们开始正式写一个样例来看看吧:

import React, { Component } from 'react';
import axios from 'axios';

export default class App extends Component {
  render() {
    return (
      <div>
        <button onClick={this.getData}>Click</button>
      </div>
    );
  }
  getData = () => {
    axios.get("http://localhost:5000/students").then(
      response => {console.log("success",response.data);},
      error => {console.log("error",error);}
    )
  }
}

我们来看代码,首先导入React这个我们就不多解释了,然后导入axios,因为我们要用axios来发送请求所以一定要引入的。我们这次直接在App组件中来编写我们的样例,因为我们目前在联系的是axios发送请求而不是组件化编码,所以为了方便就直接在App组件中来写了。

然后看App组件,我们就写了一个按钮,这个按钮我们绑定了onClick事件,并将getData方法作为事件回调。那么我们来看一看这个方法,直接axios.get发送一个GET请求,既然发送get请求我们是不是要传入一个url?不然我们请求发给谁呢?

另外一点axios发送请求返回的是一个Promise对象,那么我们是不是要调用then方法来获取这个请求发送是成功了还是失败了?成功了的话是不是获取response值,失败了我们要知道为什么失败啊,所以几首两个函数,但是Promise是不是吧我们的数据都存放在responsedata属性中了啊,所以我们要想获取数据就要调用response.data

这样的话,只要我们一点击按钮,是不是就会在控制台中打印出我们请求发送出去的情况?当然了我这里的这个url是我自己准备好的一个测试接口,我会把这个接口单独附出来。那么我们看一下效果吧:

image-20220111103452027

我们发现,诶控制台里面报错了,什么意思?这是不是在说我们跨域请求了啊?跨域的本质是什么?是因为同源策略的限制,但是同源策略都限制了些什么呢?这一部分内容大家如果不记得了,抓紧回去复习ajax跨域问题。

我们这里就简单地看,我们的前端页面地址是不是localhost:3000?而我们启动的的接口地址是不是localhost:5000?那么我们在3000端口给5000端口发请求ajax引擎能通过吗?肯定不行啊。但是我们思考一个问题,到底是因为跨域了我们请求发不出去,还是因为跨域了我请求发出去了但是数据回不来?这是两个概念,一种是连发请求都不能发,另一个是能发请求,但是拿不到数据。

实际上呢,我们其实是跨域发出去请求的,但是数据是无法传回来的,怎么证明呢?

image-20220111104333831

我们的接口界面有提醒,有人请求了接口服务器,如果说请求发不出去的话,我们是不是根本就不会出现这个接口被请求的提醒?

但是我们现在前因后果都明白了,但是我们的这个问题怎么解决呢?我们在react脚手架中跨域通过代理来解决这个问题。

代理是什么

看到这大家是不是要说终于到正题了,再不说可就忘了这节课的标题是配置代理了。但是代理到底是什么东西呢?我们怎么去理解呢?

这么说吧,当我们客户端 3000 端口要往服务端 5000 端口发送请求的时候,就一定要经过ajax引擎,ajax引擎发现客户端在 3000 端口,没问题,放行,但是服务端返回数据的时候,ajax引擎发现这个数据来源是在 5000 端口的,那么就会直接拦截下来,因为跨域了。

但是代理是个啥呢?我招一个中间人,这个中间人是 3000 端口,这一定要注意,这个中间人一定要是和客户端在同一个端口,否则也还是跨域。

那么这个情况下我们再发请求,就是先给这个中间人发请求,然后这个中间人会把我们的请求转发给服务端。然后服务端再把这个数据返回给我们的这个中间人。但是这一步为什么能走得通呢?中间人也是 3000 端口啊,服务端从 5000 端口返回数据应该也被拦下来才对啊。因为这个中间人没有ajax引擎。我们之前说数据在返回到客户端的时候被拦截了,那是谁在拦截啊?是不是ajax引擎在拦截?那么这个中间人没有ajax引擎不就不会被拦截了嘛。

那么中间人和客户端之间就更好解释了,ajax引擎发现客户端在 3000 端口,而且给 3000 端口的中间人发请求,然后这个中间人还从 3000 端口返回数据了,那么这就不跨域了啊,所以就会放行。这就是这个中间人的作用,而这个中间人,就是我们所说的代理。

如何使用代理

我们知道了代理是什么,那么我们现在怎么去使用代理呢?其实这个代理是react脚手架里的一个比较小的代理服务器,我们怎么去开启这个代理服务器呢?react脚手架中提供了两种方式,我们先给大家介绍最简单的一种:

{
  "name": "react-ajax",
  "version": "0.1.0",
  "private": true,
  "dependencies": {...},
  "scripts": {...},
  "eslintConfig": {...},
  "browserslist": {...},
  "proxy": "http://localhost:5000"
}

我们先打开项目根目录中的package.json文件,其他的都不用管,我们来在最下面加一行"proxy": "http://localhost:5000",首先proxy就是代理的意思,当我们加了这一行配置之后,就可以开启我们的代理,之后我们所有发给 3000 端口的请求都会被转发给 5000 端口。但是我们一定要把脚手架停掉,然后再重新启动才能生效。

当我们重启了脚手架之后,我是不是就可以发送请求了?并不是,我们来看我们发送请求时候请求的url,是不是还是给 5000 端口发的?那不还是一样有跨域问题嘛,那么我们应该给谁发?我们说了代理的端口一定要和客户端端口一致,那么我们是不是要把请求的url中的端口改成 3000 才行?那么我们现在再试一下效果:

image-20220111112019077

这一次我们是不是成功打印出了我们的数据?

这就是我们react脚手架中的第一种配置代理的方法

总结

  • react本身只关注界面,不包含发送ajax请求的代码
  • 前端通过ajax请求与后台交互(json数据)
  • react应用中需要集成第三方ajax库(或者自己封装)
  • 不推荐使用jQuery,推荐使用axios
  • 通过配置代理解决跨域问题
  • 代理端口一定要与客户端端口一致

Copyright statement:The articles of this site are all original if there is no special explanation, indicate the source please when you reprint.

Link of this article:https://work.lynchow.com/article/proxy_of_scaffold_1/