Appearance
受保护路由
本节目标:理解“受保护路由”的核心思路,并能把它用于实际开发或面试表达。
有权限才可以访问:
src\index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { HashRouter as Router, Route, Switch, Redirect, Link } from './react-router-dom'; import Home from './components/Home';
import User from './components/User';
import Profile from './components/Profile';
import Protected from './components/Protected'; import Login from './components/Login'; ReactDOM.render(
<Router>
<ul>
<li><Link to="/">首页</Link></li>
<li><Link to="/user" >用户管理</Link></li>
<li><Link to="/profile" >个人中心</Link></li>
</ul>
<Switch>
<Route path="/" component={Home} exact />
<Route path="/user" component={User} />
<Protected path="/profile" component={Profile} />
<Route path="/login" component={Login} /><Redirect to="/" />
</Switch>
</Router>
, document.getElementById('root'));src\react-router\Route.js
import React from 'react';
import RouterContext from './RouterContext';
import matchPath from './matchPath';
class Route extends React.Component {
static contextType = RouterContext;
render() {
const { history, location } = this.context;
const { component: RouteComponent, computedMatch, render, children } = this.props;
const match = computedMatch ? computedMatch : matchPath(location.pathname, this.props);
const routeProps = { history, location };
let renderElement = null;// null也一个合法的react渲染节点 代表我们render的返顺值,代表此组件将要渲染的内容
if (match) {
routeProps.match = match;
//RouteComponent>render>children
if (RouteComponent) {//如果传递了 component属性,优先渲染component
renderElement = <RouteComponent {...routeProps} />
} else if (render) {
renderElement = render(routeProps);
} else if (children) {
renderElement = children(routeProps);
} else {
renderElement = null;
}
} else {//TODO
if (children) {
renderElement = children(routeProps);
} else {
renderElement = null;
}
}
return renderElement
}
}
export default Route;
/**
* 指定一个route组件如何渲染有三种方式
* 1.component 如果你渲染的是一个固定 的组件,确定的组件的话就可以component
* 2.render 如果你想自己确认,自定义渲染逻辑就可以用render
*
* 1和2都是要求路径匹配才渲染或执行,如果路径不匹配什么不渲染
* 3.children
* 不管路由是否匹配,都渲染
*/src\components\Login.js
import React, { Component } from 'react'
export default class Login extends Component {
login = () => {
localStorage.setItem('login', 'true');
let to = '/';
if (this.props.location.state) {
to = this.props.location.state.to || '/';
}
this.props.history.push(to);
}
render() {
return (
<button onClick={this.login}>登录</button>
)
}
}src\components\Protected.js
import React from 'react'
import { Redirect, Route } from '../react-router-dom';
const Protected = (props) => {
const { path, component: RouteComponent } = props;
return (
<Route
path={path}
render={
(routeProps) => (
localStorage.getItem('login')
? <RouteComponent {...routeProps} />
: <Redirect to={{
pathname: '/login',
state: { from: path }
}} />
)
}
/>
)
}
export default Protected;