在Web前端开发中,咱们常常会须要处理页面路由问题。习惯上,路由信息会在一个地方集中配置好,咱们能够称之为“静态路由”,或者叫“中心化式路由”。以react-router v3版本为例,代码相似下面这样:前端
import { Router, Route, IndexRoute, browserHistory } from 'react-router'
const App = () => (
<Router history={browserHistory}>
<Route path="/" component={RootPage}>
<IndexRoute component={HomePage} />
<Route path="/users" component={UsersPage} />
</Route>
</Router>
)
render(<App />, document.getElementById('app'))
复制代码
能够看到,在程序的顶层组件上配置好了全部路由信息,并经过嵌套关系体现不一样的层次。可是,react-router v4版本进行了革命性的改动,使之更加符合React的“组件化”思想,咱们能够称之为“动态路由”,或者借用区块链中的术语,称之为“去中心化路由”。用v4版本改写后的代码相似于下面这样:react
import { BrowserRouter, Route } from 'react-router-dom'
const App = () => (
<BrowserRouter>
<RootPage />
</BrowserRouter>
)
const RootPage = () => (
<div>
<Route path="/" exact component={HomePage} />
<Route path="/users" component={UsersPage} />
</div>
)
render(<App />, document.getElementById('app'))
复制代码
能够发现,路由的配置再也不是所有位于顶层组件中了,而是分散在不一样的组件中,经过组件的嵌套关系来实现路由的层次。另外,和静态路由事先定义好全部页面不一样,动态路由能够在渲染时根据路径匹配结果,动态决定渲染哪些组件,这样就能够充分实现页面的复用,减小重复渲染。下面依次介绍react-router v4的相关组件。正则表达式
react-router内部其实是利用了浏览器的history API,所以在v3版本中咱们须要在顶层的<Router>组件中传入一个history属性。在v4版本中为咱们封装了一个<BrowserRouter>组件,咱们须要把它包在全部组件的最外层:浏览器
import { BrowserRouter } from 'react-router-dom'
const App = () => (
<BrowserRouter>
... ...
</BrowserRouter>
)
复制代码
另外还有一个<HashRouter>组件,是为了兼容之前版本的浏览器,已经不推荐使用了。bash
路由匹配主要涉及两个组件:<Route>和<Switch>,下面分别介绍。react-router
<Route>组件包含3类属性:匹配属性、渲染方法、路由属性。app
这些属性是为了设定url匹配规则。dom
(1) path:路由匹配正则表达式函数
举例:工具
<Route path='/' />:匹配以/开头的路径,好比/,/login,/login/alice
<Route path='/login/:username' />:能够匹配/login/alice,参数能够经过props.match.params.username得到
(2) exact:精确匹配
举例:
<Route path='/' exact />:只能精确匹配/,不能匹配/login
在v4版本里取消了<IndexRoute>组件,所以若是你但愿在根路径显示某个页面的话,能够用下面的方式:
<div>
<Route path="/" exact component={HomePage} />
... ...
</div>
复制代码
(3) strict:严格匹配
若是path的最后带有/,那么url必须也带有/才能匹配。举例:
<Route path='/login/' strict />:能够匹配/login/,不能匹配/login
(4) sensitive:大小写敏感
这些属性指明在匹配上路由后如何渲染。
(1) component:渲染组件
这是最多见的方式,路由匹配时渲染一个指定组件
<Route path='/users' component={UsersPage} />
(2) render:内联渲染
component方式会经过React.createElement建立新元素,而后mount到DOM上,若是须要频繁更新的话这种方式效率会比较低,这时候你能够选择内联渲染方式。
<Route path='/users' render={props => (
<div>
<Component {...props}/>
</div>
)}/>
复制代码
(3) children:根据path匹配结果渲染子元素
前面两种渲染方法都是只有path匹配时才渲染,children渲染方式则比较特殊,它是针对子元素的,而且只返回一个match结果,你能够根据match结果自行决定如何渲染子元素。举个例子,在一个列表中,咱们但愿高亮那些被匹配上的元素:
<ul>
<ListItemLink to="/somewhere" />
<ListItemLink to="/somewhere-else" />
</ul>;
const ListItemLink = ({ to, ...rest }) => (
<Route
path={to}
children={({ match }) => (
<li className={match ? "active" : ""}>
<Link to={to} {...rest} />
</li>
)}
/>
);
复制代码
这些属性能够在待渲染组件中经过props访问到。
(1) match
match属性中包含了路由匹配相关的参数:
(2) location
location中包含了当前url相关的参数:
(3) history
history就是浏览器提供的history API,提供了一些路由函数:
若是咱们但愿设置一系列的路由匹配规则,只渲染第一个匹配上的组件,该如何实现呢?这时候你就须要用到<Switch>组件。<Switch>中包含一组<Route>或者<Redirect>,只渲染第一个匹配的路由。
import { Switch, Route } from 'react-router'
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/:user" component={User}/>
<Route component={NoMatch}/>
</Switch>
复制代码
react-router提供了一系列的导航组件,基本上就是<a>标签的一个封装。主要包括3种:
举例:
import { Link, NavLink } from 'react-router-dom'
<Link to="/about">About</Link>
<NavLink to="/faq" activeClassName="selected">
FAQs
</NavLink>
复制代码
另外,react-router还提供了其余一些工具库,好比支持组件的动态import(下载)的react-loadable,支持CSS转场动画的react-transition-group,有兴趣的朋友能够自行研究一下。
最后以一张思惟导图结束本篇文章: