react-router-dom 官方示例解读
- 微信扫码关注公众号 :前端前端大前端,追求更精致的阅读体验 ,一起来学习啊
- 关注后发送关键资料,免费获取一整套前端系统学习资料和老男孩python系列课程
说明
该篇文章是对react-router-dom 官方示例的解读,例子有些会使用原始demo,有些为了方便理解会使用我自己写的。当然,如果有能力的话,还是推荐官方文档。
官方文档
BasicExample–基础实例
分析
这是一个最基础的路由示例,根据不同的url渲染不同的组件。值得注意的是,对于Route组件而言,支持的渲染组件方式
不唯一
。单标签
的时候可以使用component
属性,render
属性,或者children
属性挂载要渲染的组件。双标签
的时候包裹要渲染的组件,也就是children…
import React from 'react'
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
const Home = () => <h2>Home</h2>
const About = () => <h2>About</h2>
const Dashboard = () => <h2>Dashboard</h2>
const News = () => <h2>News</h2>
const Games = () => <h2>Games</h2>
export default function () {
return (
<Router>
<div>
<ul>
<li> <Link to="/">Home</Link> </li>
<li> <Link to="/about">About</Link> </li>
<li> <Link to="/dashboard">Dashboard</Link> </li>
<li> <Link to="/news">News</Link> </li>
<li> <Link to="/games">Games</Link> </li>
</ul>
<hr />
<Switch>
<Route exact path="/"> <Home /></Route>
<Route path="/about" component={About} />
<Route path="/dashboard" children={<Dashboard />} />
<Route path="/news" render={()=><News />} />
<Route path="/games" component={()=><Games/>} />
</Switch>
</div>
</Router>
);
}
UrlParams–动态路由
分析
该示例演示了动态路由是如何匹配的,以及如何获取匹配到的参数值。和很多框架匹配规则一致,都是
:param
.在获取参数的时候,可以用hooks形式 ,也可以用原始的props.match.params.xxx
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
Link,
useParams
} from "react-router-dom";
export default function () {
return (
<Router>
<div>
<h2>Accounts</h2>
<ul>
<li>
<Link to="/netflix/1">Netflix</Link>
</li>
<li>
<Link to="/zillow-group/2">Zillow Group</Link>
</li>
<li>
<Link to="/yahoo/3">Yahoo</Link>
</li>
<li>
<Link to="/modus-create/4">Modus Create</Link>
</li>
</ul>
<Switch>
<Route path="/:page/:num" component={Child} />
</Switch>
</div>
</Router>
);
}
function Child(props) {
let { page} = useParams();
let num=props.match.params.num;
return (
<div>
<h3>
当前页: {page}--数字:{num}
</h3>
</div>
);
}
Nesting–嵌套路由
分析
嵌套路由适用于有明显层级划分的情况,以官方示例来看,主层级分为home和topics,topics又划分出三个子主题,这就涉及到了嵌套路由。子路由的url都是在父级路由基础上拼接出来的。
像这样 /topics /topics/rendering
。值得注意的是,这个案例里用到了一个新的hooks,useRouteMatch
,这就相当于原始的props.match
.此外,这个示例里对useRouteMatch()解构了path和url,如果你打印一下,你会发现它们的值是一样的,也许就像原文解释那样,一个用来获取父路径,一个用于Link组件的跳转,更规范?
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
Link,
useParams,
useRouteMatch
} from "react-router-dom";
const Home = () => <h2>Home</h2>
const Topic = () => {
let { topicId } = useParams();
return <h3>{topicId}</h3>
}
const Topics = () => {
let { path, url } = useRouteMatch();
return (
<div>
<h2>Topics</h2>
<ul>
<li><Link to={`${url}/rendering`}>Rendering with React</Link></li>
<li><Link to={`${url}/components`}>Components</Link></li>
<li><Link to={`${url}/props-v-state`}>Props v. State</Link></li>
</ul>
<Switch>
<Route exact path={path}> <h3>Please select a topic.</h3></Route>
<Route path={`${path}/:topicId`} component={Topic} />
</Switch>
</div>
);
}
export default function () {
return (
<Router>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/topics">Topics</Link></li>
</ul>
<hr />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/topics" component={Topics} />
</Switch>
</div>
</Router>
);
}
AuthRoute–路由鉴权
分析
这是一个简化后的改写demo.核心是通过
高阶组件
+状态控制
实现路由鉴权。在实际开发中,有些页面必须登录才可以访问,甚至不同身份的人看到的页面也是不一样的。public
页面都可以访问,protected
页面必须登录才可以访问。登录状态这里使用一个变量isLogin
控制.Redirect 组件用于身份验证不通过时重定向处理,useHistory 钩子函数可获取历史记录接口,控制页面跳转。PrivateRoute 是一个高阶组件,对基础的Route进行了进一步封装,注意...rest,在这里相当于将高阶组件获取的path属性传递给Route
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
Link,
Redirect,
useHistory,
} from "react-router-dom";
let isLogin = false;
const LoginBtn = () => <button onClick={()=>{isLogin = true}}>登录</button>
const LoginOutBtn = () => {
let history=useHistory();
return <button onClick={()=>{isLogin = false;history.push("/login")}}>退出登录</button>
}
const Login = () => <LoginBtn/>
const Condition = ({ children }) => isLogin ? children : <Redirect to="/login" />
const PrivateRoute = ({ children, ...rest }) => {
return (
<Route {...rest} render={() => <Condition children={children} />} />
);
}
export default function () {
return (
<Router>
<p><Link to={"/public"} >public</Link></p>
<p><Link to={"/protected"}>protected</Link></p>
<Switch>
<Route exact path="/" render={() => <h3>home</h3>} />
<Route path="/public" render={() => <h3>public</h3>} />
<Route path="/login" component={Login} />
<PrivateRoute path="/protected">
<h2>已经登录 可查看-protected</h2>
<LoginOutBtn/>
</PrivateRoute>
</Switch>
</Router>
)
}