React - React 配置代理、搜索案例(Fetch + PubSub)、React 路由基本使用、NavLink

一、React 配置代理

1、在 package.json 文件中配置代理
(1)具体实现
  1. package.json
json 复制代码
"proxy": "http://localhost:5000"
  1. App.jsx
js 复制代码
import React, { Component } from "react";
import axios from "axios";

export default class App extends Component {
    getStudentData = () => {
        axios.get("/students").then(
            (response) => {
                console.log("成功了", response.data);
            },
            (error) => {
                console.log("失败了", error);
            },
        );
    };

    render() {
        return (
            <div>
                <button onClick={this.getStudentData}>点我获取学生数据</button>
            </div>
        );
    }
}
(2)小结
  • 工作方式:当请求了 3000 不存在的资源时,那么该请求会转发给5000(优先匹配前端资源)
  1. 优点:配置简单,前端请求资源时可以不加任何前缀

  2. 缺点:不能配置多个代理

2、在 setupProxy.js 文件中配置代理
(1)具体实现
  1. 在 src 目录下创建并配置 setupProxy.js 文件
js 复制代码
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": "" },
        }),
    );
};
  1. App.jsx
js 复制代码
import React, { Component } from "react";
import axios from "axios";

export default 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 (
            <div>
                <button onClick={this.getStudentData}>点我获取学生数据</button>
                <button onClick={this.getCarData}>点我获取汽车数据</button>
            </div>
        );
    }
}
(2)解读
  1. /api1 是需要转发的请求,target 是转发目标地址,所有带有 /api1 前缀的请求都会转发给 target
js 复制代码
createProxyMiddleware("/api1", {
    target: "http://localhost:5000",
    ...
})
  1. 控制服务器接收到的请求头中 Host 字段的值,changeOrigin 默认值为 false,但我们一般设置为 true

    1. changeOrigin 设置为 true 时,服务器收到的请求头中的 Host 字段为:localhost:5000

    2. changeOrigin 设置为 false 时,服务器收到的请求头中的 Host 字段为:localhost:3000

js 复制代码
changeOrigin: true,
  1. 去除请求前缀,保证交给后台服务器的是正常请求地址(必须配置)
js 复制代码
pathRewrite: { "^/api2": "" },
(3)小结
  1. 优点:可以配置多个代理,可以灵活的控制请求是否走代理

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


二、搜索案例(Fetch + PubSub)

  1. List 组件
js 复制代码
import React, { Component } from "react";
import PubSub from "pubsub-js";
import "./index.css";

export default class List extends Component {
    state = {
        users: [],
        isFirst: true,
        isLoading: false,
        err: "",
    };

    componentDidMount() {
        this.token = PubSub.subscribe("test", (msgName, stateObj) => {
            this.setState(stateObj);
        });
    }

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

    render() {
        const { users, isFirst, isLoading, err } = this.state;
        return (
            <div className="row">
                {isFirst ? (
                    <h3>欢迎使用,输入关键字,随后点击搜索</h3>
                ) : isLoading ? (
                    <h3>Loading...</h3>
                ) : err ? (
                    <h3 style={{ color: "red" }}>{err}</h3>
                ) : (
                    users.map((userObj) => {
                        return (
                            <div key={userObj.id} className="card">
                                <a rel="noreferrer" href={userObj.html_url} target="_blank">
                                    <img alt="head_portrait" src={userObj.avatar_url} style={{ width: "100px" }} />
                                </a>
                                <p className="card-text">{userObj.login}</p>
                            </div>
                        );
                    })
                )}
            </div>
        );
    }
}
css 复制代码
.album {
    min-height: 50rem;
    padding-top: 3rem;
    padding-bottom: 3rem;
    background-color: #f7f7f7;
}

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

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

.card-text {
    font-size: 85%;
}
  1. Search 组件
js 复制代码
import React, { Component } from "react";
import PubSub from "pubsub-js";

export default class Search extends Component {
    search = async () => {
        // 获取用户的输入(连续解构赋值 + 重命名)
        const {
            keyWordElement: { value: keyWord },
        } = this;

        // 发送请求前通知更新状态
        PubSub.publish("test", { isFirst: false, isLoading: true });

        try {
            const response = await fetch(`/api1/search/users?q=${keyWord}`);
            const data = await response.json();
            // 请求成功后通知更新状态
            PubSub.publish("test", { isLoading: false, users: data.items });
        } catch (error) {
            // 请求失败后通知更新状态
            PubSub.publish("test", { isLoading: false, err: error.message });
        }
    };

    render() {
        return (
            <section className="jumbotron">
                <h3 className="jumbotron-heading"> 搜索 GitHub 用户</h3>
                <div>
                    <input ref={(c) => (this.keyWordElement = c)} type="text" placeholder="输入关键词点击搜索" />
                    &nbsp;
                    <button onClick={this.search}>搜索</button>
                </div>
            </section>
        );
    }
}
  1. App 组件
js 复制代码
import React, { Component } from "react";
import Search from "./components/Search";
import List from "./components/List";

export default class App extends Component {
    render() {
        return (
            <div className="container">
                <Search />
                <List />
            </div>
        );
    }
}
  1. index.js
js 复制代码
import React from "react"; // 引入 React 核心库
import ReactDOM from "react-dom"; // 引入 ReactDOM
import App from "./App"; // 引入 App 组件

// 渲染 App 组件到页面
ReactDOM.render(<App />, document.getElementById("root"));
  1. setupProxy.js
js 复制代码
const { createProxyMiddleware } = require("http-proxy-middleware");

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

三、React 路由基本使用

  1. About 组件
js 复制代码
import React, { Component } from "react";

export default class About extends Component {
    render() {
        return <h3>About Content</h3>;
    }
}
  1. Home 组件
js 复制代码
import React, { Component } from "react";

export default class Home extends Component {
    render() {
        return <h3>Home Content</h3>;
    }
}
  1. App 组件
js 复制代码
import React, { Component } from "react";
import { Link, Route } from "react-router-dom";
import Home from "./components/Home";
import About from "./components/About";

export default class App extends Component {
    render() {
        return (
            <div>
                <h2>React Router Demo</h2>
                <div>
                    <Link to="/about">About</Link>
                    <Link to="/home">Home</Link>
                </div>
                <div>
                    <Route path="/about" component={About} />
                    <Route path="/home" component={Home} />
                </div>
            </div>
        );
    }
}
  1. index.js
js 复制代码
import React from "react"; // 引入 React 核心库
import ReactDOM from "react-dom"; // 引入 ReactDOM
import App from "./App"; // 引入 App 组件
import { BrowserRouter } from "react-router-dom";

// 渲染 App 组件到页面
ReactDOM.render(
    <BrowserRouter>
        <App />
    </BrowserRouter>,
    document.getElementById("root"),
);

1、基本介绍
  1. Link:单纯的页面跳转组件,提供导航功能

  2. NavLink:是 Link 的特殊版本,除了导航功能,它会自动给当前激活的链接添加样式或类名

  • NavLink 的 activeClassName 用于自定义激活类名,默认是 active
2、基本使用
  1. About 组件
js 复制代码
import React, { Component } from "react";

export default class About extends Component {
    render() {
        return <h3>About Content</h3>;
    }
}
  1. Home 组件
js 复制代码
import React, { Component } from "react";

export default class Home extends Component {
    render() {
        return <h3>Home Content</h3>;
    }
}
  1. App 组件
js 复制代码
import React, { Component } from "react";
import { NavLink, Route } from "react-router-dom";
import Home from "./components/Home";
import About from "./components/About";
import "./App.css";

export default class App extends Component {
    render() {
        return (
            <div>
                <h2>React Router Demo</h2>
                <div>
                    <NavLink activeClassName="selected" className="list-group-item" to="/about">
                        About
                    </NavLink>
                    <NavLink activeClassName="selected" className="list-group-item" to="/home">
                        Home
                    </NavLink>
                </div>
                <div>
                    <Route path="/about" component={About} />
                    <Route path="/home" component={Home} />
                </div>
            </div>
        );
    }
}
css 复制代码
.active {
    color: red;
    font-weight: bold;
    background-color: #f0f0f0;
}

.selected {
    color: blue;
    font-weight: bold;
    background-color: #f0f0f0;
}
  1. index.js
js 复制代码
import React from "react"; // 引入 React 核心库
import ReactDOM from "react-dom"; // 引入 ReactDOM
import App from "./App"; // 引入 App 组件
import { BrowserRouter } from "react-router-dom";

// 渲染 App 组件到页面
ReactDOM.render(
    <BrowserRouter>
        <App />
    </BrowserRouter>,
    document.getElementById("root"),
);
(1)pages
  1. About 组件
js 复制代码
import React, { Component } from "react";

export default class About extends Component {
    render() {
        return <h3>About Content</h3>;
    }
}
  1. Home 组件
js 复制代码
import React, { Component } from "react";

export default class Home extends Component {
    render() {
        return <h3>Home Content</h3>;
    }
}
(2)components
  • MyNavLink 组件
js 复制代码
import React, { Component } from "react";
import { NavLink } from "react-router-dom";
import "./index.css";

export default class MyNavLink extends Component {
    render() {
        return <NavLink activeClassName="selected" className="list-group-item" {...this.props} />;
    }
}
css 复制代码
.active {
    color: red;
    font-weight: bold;
    background-color: #f0f0f0;
}

.selected {
    color: blue;
    font-weight: bold;
    background-color: #f0f0f0;
}
(3)main
  1. App 组件
js 复制代码
import React, { Component } from "react";
import { Route } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import MyNavLink from "./components/MyNavLink/index";

export default class App extends Component {
    render() {
        return (
            <div>
                <h2>React Router Demo</h2>
                <div>
                    <MyNavLink to="/about">About</MyNavLink>
                    <MyNavLink to="/home">Home</MyNavLink>
                </div>
                <div>
                    <Route path="/about" component={About} />
                    <Route path="/home" component={Home} />
                </div>
            </div>
        );
    }
}
  1. index.js
js 复制代码
import React from "react"; // 引入 React 核心库
import ReactDOM from "react-dom"; // 引入 ReactDOM
import App from "./App"; // 引入 App 组件
import { BrowserRouter } from "react-router-dom";

// 渲染 App 组件到页面
ReactDOM.render(
    <BrowserRouter>
        <App />
    </BrowserRouter>,
    document.getElementById("root"),
);
相关推荐
沐知全栈开发2 小时前
R 循环:深度解析与高效运用
开发语言
The Sheep 20232 小时前
C# 操作XML
xml·前端·c#
存在的五月雨2 小时前
Nodejs的一些
前端
l14372332672 小时前
短剧出海翻译工具测评:同一段素材实测对比
大数据·前端·人工智能
小马_xiaoen2 小时前
Vue 3 + TS 实战:手写 v-no-emoji 自定义指令,彻底禁止输入框表情符号!
前端·javascript·vue.js
文心快码BaiduComate2 小时前
有奖征集|解锁Comate超能力:一文玩转Comate Skills
前端·后端
小码哥_常2 小时前
Android 集合探秘:ArrayMap 与 SparseArray 的奇妙之旅
前端
林九生2 小时前
【Flutter】Flutter 拍照/相册选择后无法显示对话框问题解决方案
前端·javascript·flutter
程序员小寒2 小时前
JavaScript设计模式(四):发布-订阅模式实现与应用
开发语言·前端·javascript·设计模式