react 路由权限守卫
程序员文章站
2022-03-24 18:43:58
...
app.js
// 路由
import {HashRouter as Router,Route,NavLink,Redirect,Switch,useHistory} from 'react-router-dom'
// 导入哈希路由(BrowserRouter浏览器路由)起别名叫Router
// Route 路由页面,NavLink 路由导航页面
import React, { Component } from 'react';
import "./App.css";
class App extends Component {
render() {
return (
<Router>
<p>
<NavLink to="/" exact>首页</NavLink> |
<NavLink to="/about">关于</NavLink> |
<NavLink to="/product/abc">产品abc</NavLink> |
<NavLink to="/product/123">产品123</NavLink> |
<NavLink to="/admin">管理</NavLink> |
<NavLink to="/private">私密</NavLink> |
<NavLink to="/login">登录</NavLink> |
</p>
<Switch>
<Route path="/" exact component={Home}></Route>
{/* <Route path="/about" component={About}></Route> */}
<Route path="/product/:id" component={Product}></Route>
<Route path="/admin" component={Admin}></Route>
<Route path="/login" component={Login}></Route>
<PrivatePage path="/private">
<Private></Private>
</PrivatePage>
<PrivatePage path="/about">
<About></About>
</PrivatePage>
<Route component={NoMatch}></Route>
</Switch>
</Router>
);
}
}
export default App;
// 权限处理
// Private 登录后 可以进入,没有登录跳转到 login 登录页面
// Login 登录页面
// PrivatePage 页面(需要权限页面都包裹再里面)
// fakeAuth登录状态记录 isAuth 是否登录 | authentic 授权登录方法 signout 注销方法
const fakeAuth = {
isAuth:false, //默认非登录状态
authentic(cb){
this.isAuth = true;//登录状态
setTimeout(cb,200);//cb登录成功后要做的callback回调函数
},
signout(cb){
this.isAuth = false;//非登录状态
setTimeout(cb,300);//cb注销成功后要做的callback回调函数
}
}
// 所有需要权限页面都放入内部 render 属性
function PrivatePage({children}){
return <Route render={({location,...rest})=>{
let component = React.cloneElement(children,rest);
// chilren 基础了 父组件的所有属性 history,match,赋值给component
// return fakeAuth.isAuth?component:<Redirect to={{pathname:"/login",state:{from:location}}}/>
return fakeAuth.isAuth?children:<Redirect to={{pathname:"/login",state:{from:location}}}/>
}}/>
// 通过state 传递当前location
}
function Private(props){
let history = useHistory();//通过hooks方式拿到history
// let history = props.history;
return(<div>
<h1>私密页面</h1>
<button onClick={()=>{
fakeAuth.signout(()=>{history.replace("/");
// 注销完毕跳转到首页
})
}}>注销</button>
</div>)
}
function Login(props){
let {from} = props.location.state||{from:{pathname:"/"}};
// 通过props接收传递过来state也就是上一个页面的location ||默认首页
return (<div>
<h1>登录页面</h1>
<button onClick={()=>{
fakeAuth.authentic(()=>{
props.history.replace(from)
})
}}>登录</button>
</div>)
}
function NoMatch({location}){
// console.log(location,"location")
// location当前页面地址栏解析 pathname 地址 query查询 hash哈希值
return (<div>
您的页面被外星人绑架了 <br/>
找不页面: {location.pathname}<br/>
<NavLink to="/" exact>回首页</NavLink>
</div>)
}
function Admin({match,location}){
return(
<div className="admin" >
<div className="leftNav" >
<NavLink to={match.url+"/user"}>用户管理</NavLink><br/>
<NavLink to={match.url+"/order"}>订单管理</NavLink>
</div>
<div className="content">
<Route path={match.url+"/user"} component={User}></Route>
<Route path={match.url+"/order"} component={Order}></Route>
{match.url==='/admin'?<Redirect from={match.url} to={match.url+"/order"} ></Redirect>:""}
</div>
</div>)
}
function User({match,location,history}){
console.log("user",match,location,history)
return (<div>
用户管理页面
</div>)
}
function Order({history}){
return (<div>
<button onClick={()=>history.goBack()}>返回</button> |
<button onClick={()=>history.push("/")}>首页</button>
<button onClick={()=>history.replace("/")}>首页-repalce</button>
<button onClick={()=>history.push({pathname:"/about",search:"?name=mumu&age=18",hash:"#good",state:{big:"super"}})}>about</button>
订单管理页面
</div>)
}
function Product({match}){
// console.log(match) //匹配的路由项 params 参数 url匹配的地址
return (<div>产品页面{match.params.id}</div>)
}
function Home(){
return (<div>首页页面</div>)
}
function About({location}){
console.log("about",location)
return (<div>关于我们页面</div>)
}
app.css
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.admin{
display:flex;
height: 80vh;
margin: 10px;
}
.leftNav{
width:200px;
border-right: 1px solid #61dafb;
}
.content{
flex: 1;
}