[尚硅谷React笔记]——第4章 React ajax

目录:

  1. 脚手架配置代理_方法一
    1. server1.js
    2. 开启服务器server1:
    3. App.js
    4. 解决跨域问题:
  2. 脚手架配置代理_方法二
    1. ​​​​​​​server2.js
    2. 开启服务器server2
    3. 第一步:创建代理配置文件
    4. 编写setupProxy.js配置具体代理规则:
    5. App.js
    6. 运行结果:
    7. 说明:
  3. github用户搜索案例
    1. github搜索案例_静态组件
    2. github搜索案例_axios发送请求
    3. github搜索案例_展示数据
    4. github搜索案例_完成案例
  4. 消息订阅与发布_pubsub
  5. fetch发送请求

1.脚手架配置代理_方法一

server1.js
const express = require('express')
const app = express()

app.use((request,response,next)=>{
	console.log('有人请求服务器1了');
	console.log('请求来自于',request.get('Host'));
	console.log('请求的地址',request.url);
	next()
})

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

app.listen(5000,(err)=>{
	if(!err) console.log('服务器1启动成功了,请求学生信息地址为:http://localhost:5000/students');
})
开启服务器server1:

[尚硅谷React笔记]——第4章 React ajax_第1张图片

App.js
import React, {Component} from 'react';
import axios from "axios";

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

    render() {
        return (
            
); } } export default App;
解决跨域问题:

package.json

{
  "name": "20231003",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.17.0",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "axios": "^1.5.1",
    "nanoid": "^5.0.1",
    "prop-types": "^15.8.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "proxy": "http://localhost:5000"
  }
}

使用方法一遇到了bug,去stackoverflow解决一下,能解决,但是有更好的方法,方法一不在继续了.node.js - Invalid options object. Dev Server has been initialized using an options object that does not match the API schema - Stack Overflow

2.脚手架配置代理_方法二

server2.js
const express = require('express')
const app = express()

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

app.get('/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启动成功了,请求汽车信息地址为:http://localhost:5001/cars');
})
开启服务器server2

[尚硅谷React笔记]——第4章 React ajax_第2张图片

访问端口:

[尚硅谷React笔记]——第4章 React ajax_第3张图片

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

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

编写setupProxy.js配置具体代理规则:

这个适合低版本

const proxy = require('http-proxy-middleware')

module.exports = function(app) {
  app.use(
    proxy('/api1', {  //api1是需要转发的请求(所有带有/api1前缀的请求都会转发给5000)
      target: 'http://localhost:5000', //配置转发目标地址(能返回数据的服务器地址)
      changeOrigin: true, //控制服务器接收到的请求头中host字段的值
      /*
          changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
          changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:3000
          changeOrigin默认值为false,但我们一般将changeOrigin值设为true
      */
      pathRewrite: {'^/api1': ''} //去除请求前缀,保证交给后台服务器的是正常请求地址(必须配置)
    }),
    proxy('/api2', { 
      target: 'http://localhost:5001',
      changeOrigin: true,
      pathRewrite: {'^/api2': ''}
    })
  )
}

我使用的node是:v18.18.0 

//react 18版本写法
const {createProxyMiddleware} = require('http-proxy-middleware')

module.exports = function (app) {
    app.use(
        createProxyMiddleware('/api1', {
            target: 'http://localhost:5000',
            changeOrigin: true,
            pathRewrite: {'^/api1': ''}
        }),
        createProxyMiddleware('/api2', {
            target: 'http://localhost:5001',
            changeOrigin: true,
            pathRewrite: {'^/api2': ''}
        }),
    )
}
App.js 
import React, {Component} from 'react';
import axios from "axios";

class App extends Component {
    getStudentData = () => {
        axios.get('http://localhost:3000/api1/students').then(
            response => {
                console.log('成功了', response.data);
            },
            error => {
                console.log('失败了', error);
            }
        )
    }

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

    render() {
        return (
            
); } } export default App;

运行结果:

[尚硅谷React笔记]——第4章 React ajax_第4张图片

说明:
  1. 优点:可以配置多个代理,可以灵活的控制请求是否走代理。

  2. 缺点:配置繁琐,前端请求资源时必须加前缀。

3.github用户搜索案例

github搜索案例_静态组件

App.js

import React, {Component} from 'react';
import Search from './components/Search/Search'
import List from "./components/List/List";

class App extends Component {
    render() {
        return (
            
); } } export default App;

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render();

 List.jsx

import React, {Component} from 'react';
import './List.css'

class List extends Component {
    render() {
        return (
            
head_protrait

reactjs

); } } export default List;

 List.css

.album {
    min-height: 50rem; /* Can be removed; just added for demo purposes */
    padding-top: 3rem;
    padding-bottom: 3rem;
    background-color: #f7f7f7;
}

.card {
    float: left;
    width: 33.333%;
    padding: .75rem;
    margin-bottom: 2rem;
    border: 1px solid #efefef;
    text-align: center;
}

.card > img {
    margin-bottom: .75rem;
    border-radius: 100px;
}

.card-text {
    font-size: 85%;
}

Search.jsx

import React, {Component} from 'react';

class Search extends Component {
    render() {
        return (
            

Search Github Users

 
); } } export default Search;

运行结果:

[尚硅谷React笔记]——第4章 React ajax_第5张图片 

github搜索案例_axios发送请求

demo.html




    
    Title




server.js

const express = require("express")
const axios = require("axios")
const app = express()


/*
  请求地址: http://localhost:3000/search/users?q=aa

  后台路由
    key: /search/users
    value: function () {}
*/
app.get("/search/users", function (req, res) {
  const {q} = req.query
  axios({
    url: 'https://api.github.com/search/users',
    params: {q}
  }).then(response => {
    res.json(response.data)
  })
})

app.get("/search/users2", function (req, res) {
  res.json({
    items: [
      {
        login: "yyx990803",
        html_url: "https://github.com/yyx990803",
        avatar_url:
          "https://avatars3.githubusercontent.com/u/499550?s=460&u=de41ec9325e8a92e281b96a1514a0fd1cd81ad4a&v=4",
        id: 1,
      },
      {
        login: "ruanyf",
        html_url: "https://github.com/ruanyf",
        avatar_url: "https://avatars2.githubusercontent.com/u/905434?s=460&v=4",
        id: 2,
      },
      {
        login: "yyx9908032",
        html_url: "https://github.com/yyx990803",
        avatar_url:
          "https://avatars3.githubusercontent.com/u/499550?s=460&u=de41ec9325e8a92e281b96a1514a0fd1cd81ad4a&v=4",
        id: 3,
      },
      {
        login: "ruanyf2",
        html_url: "https://github.com/ruanyf",
        avatar_url: "https://avatars2.githubusercontent.com/u/905434?s=460&v=4",
        id: 4,
      },
      {
        login: "yyx9908033",
        html_url: "https://github.com/yyx990803",
        avatar_url:
          "https://avatars3.githubusercontent.com/u/499550?s=460&u=de41ec9325e8a92e281b96a1514a0fd1cd81ad4a&v=4",
        id: 5,
      },
      {
        login: "ruanyf3",
        html_url: "https://github.com/ruanyf",
        avatar_url: "https://avatars2.githubusercontent.com/u/905434?s=460&v=4",
        id: 6,
      },
      {
        login: "yyx9908034",
        html_url: "https://github.com/yyx990803",
        avatar_url:
          "https://avatars3.githubusercontent.com/u/499550?s=460&u=de41ec9325e8a92e281b96a1514a0fd1cd81ad4a&v=4",
        id: 7,
      },
      {
        login: "ruanyf4",
        html_url: "https://github.com/ruanyf",
        avatar_url: "https://avatars2.githubusercontent.com/u/905434?s=460&v=4",
        id: 8,
      },
      {
        login: "yyx9908035",
        html_url: "https://github.com/yyx990803",
        avatar_url:
          "https://avatars3.githubusercontent.com/u/499550?s=460&u=de41ec9325e8a92e281b96a1514a0fd1cd81ad4a&v=4",
        id: 9,
      },
    ],
  });
});



app.listen(5000, "localhost", (err) => {
  if (!err){
  	console.log("服务器启动成功")
  	console.log("请求github真实数据请访问:http://localhost:5000/search/users")
  	console.log("请求本地模拟数据请访问:http://localhost:5000/search/users2")
  } 
  else console.log(err);
})

启动服务器:

node .\server.js

[尚硅谷React笔记]——第4章 React ajax_第6张图片 App.js

import React, {Component} from 'react';
import Search from './components/Search/Search'
import List from "./components/List/List";

class App extends Component {
    render() {
        return (
            
); } } export default App;

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render();

List.jsx

import React, {Component} from 'react';
import './List.css'

class List extends Component {
    render() {
        return (
            
head_protrait

reactjs

); } } export default List;

List.css

.album {
    min-height: 50rem; /* Can be removed; just added for demo purposes */
    padding-top: 3rem;
    padding-bottom: 3rem;
    background-color: #f7f7f7;
}

.card {
    float: left;
    width: 33.333%;
    padding: .75rem;
    margin-bottom: 2rem;
    border: 1px solid #efefef;
    text-align: center;
}

.card > img {
    margin-bottom: .75rem;
    border-radius: 100px;
}

.card-text {
    font-size: 85%;
}

Search.jsx

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

class Search extends Component {
    search = () => {
        //连续结构+重命名
        const {keyWordElement: {value: keyWord}} = this

        axios.get(`http://localhost:3000/api1/search/users2?q=${keyWord}`).then(
            response => {
                console.log('成功了', response.data);
            },
            error => {
                console.log('失败了', error);
            }
        )
    }

    render() {
        return (
            

搜索github用户

this.keyWordElement = c} type="text" placeholder="输入关键词点击搜索"/> 
); } } export default Search;

 setupProxy.js

//react 18版本写法
const {createProxyMiddleware} = require('http-proxy-middleware')

module.exports = function (app) {
    app.use(
        createProxyMiddleware('/api1', {
            target: 'http://localhost:5000',
            changeOrigin: true,
            pathRewrite: {'^/api1': ''}
        }),
    )
}

 

运行结果:

[尚硅谷React笔记]——第4章 React ajax_第7张图片 

github搜索案例_展示数据

App.js

import React, {Component} from 'react';
import Search from './components/Search/Search'
import List from "./components/List/List";

class App extends Component {
    state = {users: []}

    saveUsers = (users) => {
        this.setState({users})
    }

    render() {
        const {users} = this.state
        return (
            
); } } export default App;

List.jsx

import React, {Component} from 'react';
import './List.css'

class List extends Component {
    render() {
        return (
            
{ this.props.users.map((userObj) => { return (
head_protrait

{userObj.login}

) }) }
); } } export default List;

 Search.jsx

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

class Search extends Component {
    search = () => {
        //连续结构+重命名
        const {keyWordElement: {value: keyWord}} = this

        axios.get(`http://localhost:3000/api1/search/users2?q=${keyWord}`).then(
            response => {
                console.log('成功了', response.data.items);
                this.props.saveUsers(response.data.items)
            },
            error => {
                console.log('失败了', error);
            }
        )
    }

    render() {
        return (
            

搜索github用户

this.keyWordElement = c} type="text" placeholder="输入关键词点击搜索"/> 
); } } export default Search;

运行结果:

[尚硅谷React笔记]——第4章 React ajax_第8张图片

github搜索案例_完成案例

App.js

import React, {Component} from 'react';
import Search from './components/Search/Search'
import List from "./components/List/List";

class App extends Component {
    state = {users: [], isFirst: true, isLoading: false, err: ''}

    saveUsers = (users) => {
        this.setState({users})
    }

    updateAppState = (stateObj) => {
        this.setState(stateObj)
    }

    render() {
        const {users} = this.state
        return (
            
); } } export default App;

Search.jsx

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

class Search extends Component {
    search = () => {
        //连续结构+重命名
        const {keyWordElement: {value: keyWord}} = this
        console.log(keyWord)

        this.props.updateAppState({isFirst: false, isLoading: true})

        axios.get(`http://localhost:3000/api1/search/users2?q=${keyWord}`).then(
            response => {
                console.log('成功了', response.data.items);
                this.props.updateAppState({isLoading: false, users: response.data.items})
            },
            error => {
                console.log('失败了', error);
                this.props.updateAppState({isLoading: false, err: error.message})
            }
        )
    }

    render() {
        return (
            

搜索github用户

this.keyWordElement = c} type="text" placeholder="输入关键词点击搜索"/> 
); } } export default Search;

List.jsx

import React, {Component} from 'react';
import './List.css'

class List extends Component {
    render() {
        const {users, isFirst, isLoading, err} = this.props
        return (
            
{ isFirst ?

欢迎使用,输入关键字,然后点击搜索

: isLoading ?

加载中...

: err ?

{err}

: users.map((userObj) => { return (
head_protrait

{userObj.login}

) }) }
); } } export default List;

 setProxy.js

//react 18版本写法
const {createProxyMiddleware} = require('http-proxy-middleware')

module.exports = function (app) {
    app.use(
        createProxyMiddleware('/api1', {
            target: 'http://localhost:5000',
            changeOrigin: true,
            pathRewrite: {'^/api1': ''}
        }),
    )
}

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render();

运行结果:

[尚硅谷React笔记]——第4章 React ajax_第9张图片

4.消息订阅与发布_pubsub

App.js

import React, {Component} from 'react';
import Search from './components/Search/Search'
import List from "./components/List/List";

class App extends Component {
    render() {
        return (
            
); } } export default App;

List.jsx

import React, {Component} from 'react';
import './List.css'
import PubSub from 'pubsub-js'

class List extends Component {
    state = {users: [], isFirst: true, isLoading: false, err: ''}

    componentDidMount() {
        this.token = PubSub.subscribe('atguigu', (_, stateObj) => {
            console.log(stateObj);
            this.setState(stateObj);
        })
    }

    componentWillUnmount() {
        PubSub.unsubscribe(this.token)
    }

    render() {
        const {users, isFirst, isLoading, err} = this.state
        return (
            
{ isFirst ?

欢迎使用,输入关键字,然后点击搜索

: isLoading ?

加载中...

: err ?

{err}

: users.map((userObj) => { return (
head_protrait

{userObj.login}

) }) }
); } } export default List;

 Search.jsx

import React, {Component} from 'react';
import axios from "axios";
import PubSub from "pubsub-js";

class Search extends Component {
    search = () => {
        //连续结构+重命名
        const {keyWordElement: {value: keyWord}} = this
        console.log(keyWord)

        // this.props.updateAppState({isFirst: false, isLoading: true})
        PubSub.publish('atguigu', {isFirst: false, isLoading: true})

        axios.get(`http://localhost:3000/api1/search/users2?q=${keyWord}`).then(
            response => {
                console.log('成功了', response.data.items);
                // this.props.updateAppState({isLoading: false, users: response.data.items})
                PubSub.publish('atguigu', {isLoading: false, users: response.data.items})
            },
            error => {
                console.log('失败了', error);
                // this.props.updateAppState({isLoading: false, err: error.message})
                PubSub.publish('atguigu', {isLoading: false, err: error.message})
            }
        )

    }

    render() {
        return (
            

搜索github用户

this.keyWordElement = c} type="text" placeholder="输入关键词点击搜索"/> 
); } } export default Search;

setupProxy.js

//react 18版本写法
const {createProxyMiddleware} = require('http-proxy-middleware')

module.exports = function (app) {
    app.use(
        createProxyMiddleware('/api1', {
            target: 'http://localhost:5000',
            changeOrigin: true,
            pathRewrite: {'^/api1': ''}
        })
    )
}

运行结果:

[尚硅谷React笔记]——第4章 React ajax_第10张图片

5.fetch发送请求

Search.jsx

import React, {Component} from 'react';
import axios from "axios";
import PubSub from "pubsub-js";

class Search extends Component {
    search = async () => {
        //连续结构+重命名
        const {keyWordElement: {value: keyWord}} = this

        PubSub.publish('atguigu', {isFirst: false, isLoading: true})

        try {
            const response = await fetch(`http://localhost:3000/api1/search/users2?q=${keyWord}`)
            const data = await response.json()
            console.log(data)
            PubSub.publish('atguigu', {isLoading: false, users: data.items})
        } catch (error) {
            console.log('请求出错', error)
            PubSub.publish('atguigu', {isLoading: false, err: error.message})
        }
    }

    render() {
        return (
            

搜索github用户

this.keyWordElement = c} type="text" placeholder="输入关键词点击搜索"/> 
); } } export default Search;

ajax,fetch,xhr,axios,jquery之间的关系 

[尚硅谷React笔记]——第4章 React ajax_第11张图片 

运行结果:

[尚硅谷React笔记]——第4章 React ajax_第12张图片

你可能感兴趣的:(#,React,react.js,笔记,前端)