React 路由拦截
#
第一种方式// 根文件 App.jsximport React from "react";import { BrowserRouter, NavLink, Route } from "react-router-dom";import MyPrompt from "./MyPrompt";import Login from "./Login";const App = () => { // 做一个全局的标识 window.sessionStorage.setItem("user", "false"); // 判断是否登录过,如果有登录的值,直接更改为true 主要是为了模拟登录以后就不能再跳转登录页面,而是去首页 // const state = window.sessionStorage.getItem("user", "false"); // if (!state) { // window.sessionStorage.setItem("user", "false"); // } return ( // 路由之容器 <BrowserRouter> <header> <nav> {/* 路由之导航 */} <NavLink to="/">首页</NavLink> | <NavLink to="/news">新闻</NavLink> | <NavLink to="/login">登陆</NavLink> </nav> </header> {/* 路由之线路 */} <Route component={MyPrompt} /> <Route path="/" component={() => <h1>首页内容</h1>} exact /> <Route path="/news" component={() => <h1>新闻内容!!</h1>} /> <Route path="/login" component={Login} /> </BrowserRouter> );};export default App;
// 登录页 loginimport React from "react";
const Login = (props) => { // finish 结束函数 const onFinish = (values) => { // 登陆成功的函数 window.sessionStorage.setItem("user", "true"); // 跳转 props.history.replace("/"); console.log("Success:", values); }; return (<> <input name="username" onFinish={onFinish} type="text" /> <input name="password" type="text" /> <button onClick={onFinish} >登录</button> </>);};
export default Login;
// 路由拦截逻辑页 (本页不会渲染到页面上,主要功能就是拦截)import React from "react";import { Prompt, useHistory } from "react-router-dom";const Com = () => { const getHistory = (history) => { const location = history.location; const user = window.sessionStorage.getItem("user"); if (location.pathname === "/login" && user === "true") { history.replace("/"); } else if (location.pathname === "/" && user === "false") { history.replace("/login"); } }; getHistory(useHistory()); return ( <> <Prompt message={function (location) { // location是下一个路由的信息 const user = window.sessionStorage.getItem("user"); if (location.pathname === "/login" && user === "true") { return false; } else if (location.pathname === "/" && user === "false") { return false; } else { return true; } }} /> </> );};
export default Com;
#
第二种方式 项目 + 后台#
后台- 主文件 -- index.js
// express// corsvar express = require("express");var cors = require("cors");var BodyParser = require("body-parser");var app = express();// 使用跨域函数,允许所有的地址请求app.use(cors());// post参数解析// body-parserapp.use(BodyParser.json());app.use( BodyParser.urlencoded({ extended: true, }));
// 开启一个服务器app.listen(3001, () => console.log("http://loclhost:3001"));
// 创建后端路由---给前端用的接口app.get("/home", (request, response) => { // 假数据 const imgs = [ "https://images.unsplash.com/photo-1668123508904-a49a9aa6ecb8?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw0MHx8fGVufDB8fHx8&auto=format&fit=crop&w=800&q=60", "https://images.unsplash.com/photo-1668123508904-a49a9aa6ecb8?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw0MHx8fGVufDB8fHx8&auto=format&fit=crop&w=800&q=60", "https://images.unsplash.com/photo-1668123508904-a49a9aa6ecb8?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw0MHx8fGVufDB8fHx8&auto=format&fit=crop&w=800&q=60", ]; // 接口要返回给前端数据 response.json({ code: 1, msg: "成功!", datas: imgs, });});
// 假数据库let db = [];// { username: "songyu", password: "123456", state: 0 }// 注册接口app.post("/reg", (req, res) => { // 后端校验一下 // 通过校验后存入临时的数组【数据库】里 db.push({ ...req.body, state: 0 }); // 对前端请求做响应 res.json({ code: 1, msg: "注册成功!" });});// 登陆接口app.post("/login", (req, res) => { // get方式取参:query post方式取参:body const { username, password } = req.body; // 1. 对参数判断 // 2. 从db数据里查询 const index = db.findIndex( (item) => item.username === username && item.password === password ); // 3. 做出响应 if (index !== -1) { // 修改data db[index].state = 1; res.json({ code: 1, msg: "登陆成功" }); } else { res.json({ code: 0, msg: "登陆失败!" }); }});// 退出接口
- package.json
{ "name": "backend", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "nodemon index.js" }, "author": "", "license": "ISC", "dependencies": { "body-parser": "^1.19.0", "cors": "^2.8.5", "express": "^4.17.1" }}
#
前端api
接口文档
// base.jsimport axios from "axios";const Axios = axios.create({ // 公共的基础的后端请求地址 baseURL: "http://localhost:3001",});export default Axios;
// home.jsimport Axios from "./base";// 首页的基础信息请求export const getHome = () => { return Axios.get("/home");};
// reg.js 注册import Axios from "./base";export const reg = (query) => { return Axios.post("/reg", query);};
// login.jsimport Axios from "./base";export const login = (query) => { return Axios.post("/login", query);};
// react 主文件 Layout.jsximport React from "react";import { BrowserRouter, NavLink, Route, Redirect } from "react-router-dom";// 引入路由配置文件import routes from "./router/index";// 引入路由拦截文件import MyPrompt from "./MyPrompt";const Com = () => { // 创建一个全局数据存储 const userstate = window.sessionStorage.getItem("user"); if (!userstate) { window.sessionStorage.setItem("user", "false"); } return ( <BrowserRouter> <MyPrompt /> {/* 导航 */} <NavLink to="/home">首页</NavLink> <NavLink to="/login">登陆</NavLink> <NavLink to="/reg">注册</NavLink> {/* 线路 */} {routes.map((item, index) => { return ( <Route key={index} path={item.path} component={(props) => { const state = window.sessionStorage.getItem("user"); // 根据拦截判断 做出渲染 if (!item.auth) { if (state === "false") { return <item.component {...props} />; } else { return <Redirect to="/home" />; } } else { if (state === "true") { return <item.component {...props} />; } else { return <Redirect to="/login" />; } } }} /> ); })} </BrowserRouter> );};export default Com;// 文件中引入了两个文件 routes MyPrompt
MyPrompt.jsx
文件
// MyPrompt.jsximport { Prompt, withRouter } from "react-router-dom";const MyPrompt = (props) => { return ( // Prompt是在页面离开的时候触发 // location即将进入的下一个路由信息 // 在这里做拦截判断 <> <Prompt message={(location) => { const state = window.sessionStorage.getItem("user"); if ( (location.pathname === "/" || location.pathname === "/home") && state === "false" ) { return false; } else if ( location.pathname !== "/" && location.pathname !== "/home" && state === "true" ) { return false; } return true; }} /> </> );};export default withRouter(MyPrompt);
- 路由配置文件 routes.js
// routes.jsconst routes = [ { exact: true, auth: true, path: "/", component: require("../Home").default, }, { path: "/reg", component: require("../Registy").default, }, { path: "/login", component: require("../Login").default, },];export default routes;
- Home.jsx 首页文件
// Home.jsximport React, { useState, useEffect } from "react";import { getHome } from "./api/home";import { Carousel } from "antd";
const Com = () => { // 用于渲染页面的home数据对象 const [home, setHome] = useState([]); // 当页面加载完成,发起一个自动请求 useEffect(() => { // 开启请求 getHome().then((res) => { if (res.data.code === 1) { setHome(res.data.datas); } else { alert("请求失败!"); } }); }, []); return ( <div> <Carousel autoplay> {home.map((value, index) => { return ( <div key={index}> <img src={value} /> </div> ); })} </Carousel> </div> );};export default Com;
- login.jsx 注册和登录文档基本一致
// login.jsximport React, { useState } from "react";// 引入接口文档import { login } from "./api/login";
const Com = (props) => { const [user, setUser] = useState({ username: "", password: "", }); // 赋值函数 const changeUser = (event) => { const input = event.target; setUser({ ...user, [input.name]: input.value, }); }; // 提交 const submit = () => { // 前端的基础校验 // 发起一个请求 login(user).then((res) => { // 1. res.code 1 跳到首页,并且修改全局用户状态 // 2. res.code 0 跳到注册页 if (res.data.code) { window.sessionStorage.setItem("user", "true"); props.history.replace("/home"); } else { props.history.replace("/reg"); } }); }; return ( <div> <input onChange={changeUser} type="text" name="username" value={user.username} /> <br /> <input onChange={changeUser} name="password" type="password" value={user.password} /> <br /> <button onClick={submit}>登陆</button> </div> );};export default Com;
- reg.jsx
// reg.jsximport React, { useState } from "react";import { reg } from "./api/reg";
const Com = (props) => { const [user, setUser] = useState({ username: "", password: "", }); // 赋值函数 const changeUser = (event) => { const input = event.target; setUser({ ...user, [input.name]: input.value, }); }; // 提交 const submit = () => { // 前端的基础校验 // 发起一个请求 reg(user).then((res) => { // 1. code 1 跳到登陆 0 提示出错! if (res.data.code) { props.history.replace("/login"); } else { alert(res.data.msg || "注册失败!"); } }); }; return ( <div> <input onChange={changeUser} type="text" name="username" value={user.username} /> <br /> <input onChange={changeUser} name="password" type="password" value={user.password} /> <br /> <button onClick={submit}>注册</button> </div> );};export default Com;