现在有3个页面
- Home 页面
- Login 页面
- Personal 页面(受保护,未登录无法进入)
1,实现
import { BrowserRouter as Router, Route, Switch, Link, Redirect } from "react-router-dom";
import ProtectedRoute from "./ProtectedRoute";
import loginInfo from "./loginInfo";
function Login(props) {
return (
<>
<h1>登录页</h1>
<button
onClick={() => {
loginInfo.login();
// 跳转进入 login 之前,准备进入的页面(受保护页面)
if (props.location.state) {
props.history.replace(props.location.state);
} else {
props.history.replace("/");
}
}}
>
登录
</button>
</>
);
}
function Home() {
return (
<>
<h1>Home页</h1>
<Link to="/personal">个人中心</Link>
</>
);
}
function Personal() {
return <h1>个人中心页</h1>;
}
export default function App() {
return (
<Router>
<Switch>
<Route path="/login" component={Login}></Route>
<ProtectedRoute path="/personal" component={Personal}></ProtectedRoute>
<Route component={Home}></Route>
</Switch>
</Router>
);
}
自定义的 ProtectedRoute 组件。使用方式和 Route 组件一样(参数一致),但需要登录才能进入。
import React from "react";
import { Route, Redirect } from "react-router-dom";
import loginInfo from "./loginInfo";
export default function ProtectedRoute({ component: Comp, children, ...rest }) {
return (
<Route
{...rest}
render={(values) => {
return loginInfo.isLogin ? <Comp /> : <Redirect to={{ pathname: "/login", state: values.location.pathname }}></Redirect>;
}}
></Route>
);
}
2,知识点
1,Route.children 和 Route.render
2个都是函数,参数是路由信息(history
,location
,match
)。
区别:render
只有当路由匹配时才会执行,children
无论是否匹配都会执行。
注意,上面的示例中因为使用了
Switch
组件,所以只会渲染一个路由组件,此时render
和children
表现是一致的。
2,保存跳转 login 之前的路由
一般当跳转受保护路由时,如果进入了 /login
,则需要保留之前的路由,方便登录后直接进入。
- 方式1:将该路由路径作为
search
参数保留,之后跳转。 - 方式2,将该路径路径保存在
state
中(push 的第2个参数),之后跳转。上面的例子用的该方式。
3,解构参数
如果传递的对象中,需要传递给其他组件,但有的属性不用传递。
此时,可以使用解构+剩余参数,参考上面的 ProtectedRoute
组件。
以上。