使用 React-Router 实现权限拦截分离。
假设应用有3个组件,一个显示登录状态的组件,一个公开信息组件,一个私有信息丝丝组件,其中私有信息需要在用户登录之后才能访问。根据此逻辑应用需要一个登录状态组件,一个公开信息组件,一个私有信息组件,分别把它们定义成组件:AuthPage,Login,Public,Private。
Login
1 2 3 4 5 6 7 8 9 10 11
| const fakeAuth = { isAuthenticated: false, authenticate(cb) { this.isAuthenticated = true setTimeout(cb, 1000) }, signout(cb) { this.isAuthenticated = false setTimeout(cb, 1000) } }
|
使用 fakeAuth 对象来管理用户的登录状态,以及 登录、登出 操作。
当用户未登录的时候去访问私有信息,应用会让用户先登录,登录成功之后,自动跳转回私有信息页面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| class Login extends React.Component { constructor(props) { super(props); this.state = { redirectToReferrer: false } this.login = ()=> { fakeAuth.authenticate(() => { this.setState({redirectToReferrer: true}) }) } } render() { const {from} = this.props.location.state || {from: {pathname: '/'}} const {redirectToReferrer} = this.state if (redirectToReferrer) { return ( <Redirect to={from}/> ) } return ( <div> <p>若想访问 {from.pathname} ,你需要先登录</p> <button onClick={this.login}>登录</button> </div> ) } }
|
AuthPage
1 2 3 4 5 6 7 8 9
| const AuthPage = withRouter(({history}) => { return fakeAuth.isAuthenticated ? (<p>Welcome! <button onClick={()=>{ fakeAuth.signout(()=>history.push('/')) }}>Signout</button> </p>) : (<p>You're not Logined!</p>) })
|
在登录态组件中,根据用户的登录状态,如果未登录则显示未登录信息,如果已经登录,则显示登录状态,并且用户可以点击登出按钮退出登录。
Public
1 2 3
| const Public = () => { return (<h3>公开的页面</h3>) }
|
Private
1
| const Private = () => <h3>非公开的页面</h3>
|
Router
1 2 3 4 5 6 7 8 9 10 11 12
| var router = (<BrowserRouter> <div> <AuthPage /> <ul> <li><Link to="/public">public page</Link></li> <li><Link to="/private">private page</Link></li> </ul> <Route path="/public" component={Public}/> <Route path="/login" component={Login}/> <PrivateRoute path="/private" component={Private}/> </div> </BrowserRouter>)
|
定义好应用程序的 Router,Router 中定义了三个路径,/public,/login,/private。其中,对于 /private 路径和 Private 组件做了一点特殊的处理,使用一个 PrivateRoute 来定义该 Route。
PrivateRoute
1 2 3 4 5 6 7 8 9 10 11 12 13
| const PrivateRoute = ({component: Component, ...rest}) => { console.log(rest); return ( <Route {...rest} render={props => ( fakeAuth.isAuthenticated ? (<Component {...props}/>) : (<Redirect to={{ pathname: '/login', state: { from: props.location } }}/>) )}/>) }
|
在 PrivateRoute 中,如果用户已经登录,则直接渲染该 Route 中的 component 属性所对应的组件,如果未登录,则使用 Redirect 组件转向 /login 登录页面。通过这样的处理,在应用程序中,在同一时刻只会是 登录态 或者 未登录态。