React 路由拦截
ZGuangJu 10/26/2020 react
# 第一种方式
// 根文件 App.jsx
import 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;
// 登录页 login
import 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
// cors
var express = require("express");
var cors = require("cors");
var BodyParser = require("body-parser");
var app = express();
// 使用跨域函数,允许所有的地址请求
app.use(cors());
// post参数解析
// body-parser
app.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://tse4-mm.cn.bing.net/th/id/OIP.TyO2Zk9rimhW6JAPF6qWiQHaEo?w=265&h=180&c=7&o=5&pid=1.7",
"https://tse1-mm.cn.bing.net/th/id/OIP.zuaft90i2OgD-0oMvkO9bwHaEK?w=255&h=180&c=7&o=5&pid=1.7",
"https://tse4-mm.cn.bing.net/th/id/OIP.TyO2Zk9rimhW6JAPF6qWiQHaEo?w=265&h=180&c=7&o=5&pid=1.7",
];
// 接口要返回给前端数据
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.js
import axios from "axios";
const Axios = axios.create({
// 公共的基础的后端请求地址
baseURL: "http://localhost:3001",
});
export default Axios;
// home.js
import 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.js
import Axios from "./base";
export const login = (query) => {
return Axios.post("/login", query);
};
// react 主文件 Layout.jsx
import 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.jsx
import { 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.js
const 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.jsx
import 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.jsx
import 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.jsx
import 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;