官网地址
https://reactrouter.com/web/guides/quick-start
React Router 的组成部分
react-router : 是浏览器与原生应用的公共部分。
react-router-dom:是用于浏览器的。
react-router-native: 是用于原生应用的。
react-router
是核心部分。react-router-dom
提供了浏览器使用需要的定制组件。react-router-native
则专门提供了在原生移动应用中需要用到的部分。所以,如果在本例中实现浏览器开发就只需要安装react-router-dom
。
安装react-router-dom
执行以下命令
npm install react-router-dom --save
react-router
Browser Router : 这是对
Router
接口的实现。使得页面和浏览器的history保持一致。如:window.location
。Hash Router : 和上面的一样,只是使用的是 URL 的hash部分,比如:
window.location.hash
。Native Router: 处理react native内的路由。
Static Router: 处理静态路由。
<BrowserRouter>
和<HashRouter>
是可以在浏览器中使用的。如果你使用的是一个非静态的站点、要处理各种不同的URL那么你就需要使用BrowserRouter
。相反的如果你的server只处理静态的URL,那么就使用HashRouter
。**
route
Route
组件可以使用如下的属性:
path属性,字符串类型,它的值就是用来匹配url的。
component属性,它的值是一个组件。在
path
匹配成功之后会绘制这个组件。exact属性,这个属性用来指明这个路由是不是排他的匹配。
strict属性, 这个属性指明路径只匹配以斜线结尾的路径。
还有其他的一些属性,可以用来代替component
属性。
render属性,一个返回React组件的方法。传说中的rencer-prop就是从这里来的。
children属性,返回一个React组件的方法。只不过这个总是会绘制,即使没有匹配的路径的时候。
多数的时候是用component
属性就可以满足。但是,某些情况下你不得不使用render
或children
属性。
- match
- location
- history
如:
使用组件:
<Route exact path="/" component={HomePage} />
使用`render`属性实现内联绘制:
<Route path="/" render={()=><div>HomePage</div>} />
const FadingRoute = ({ component, ...rest }) => (
<Route {...rest} render={(props) => (
<FadeIn>
<componnet {...props} />
</FadeIn>
)} />
)
<FadingRoute path="/cool" component={Something} />
使用`children`:
<ul>
<ListItemLink to="/somewhere" />
<LinkItemLink to="/somewhere-else" />
</ul>
const ListItemLink = ({to, ...rest}) => (
<Route path={to} children={({math}) => (
<li className={match ? 'active' : ''}>
<Link to={to} {...rest} />
</li>
)} />
)
URL / Path / Route 的参数
通常情况下,我们都会在路径里添加参数。这样方便在不同的组件之间传递一些必要的数据。那么我们如何才能获取到这些传递的参数,并传递给组件中呢?我们只需要在路径的最后加上/:param
。如:
<Route path="/:param1" component={HomePage} />
const HomePage = ({match}) => (
<div>
<h1> parameter => {match.params.param1} </h1>
</div>
);
一旦有路径可以匹配成功,那么就会穿件一个拥有如下属性的对象,并传入绘制的组件里:
- url: 匹配的url。
- path:就是path。
- isExact:如果
path
和当前的widnow.location
的path部分完全相同的话。 - params:在URL里包含的参数。
Link
Link
是react router v4特有的一个组件。是用来代替上一版的anchor link。使用Link
可以在React应用的不同页面之间跳转。与unclor会重新加载整个页面不同,Link
只会重新加载页面里和当前URL可以匹配的部分
Link
组件需要用到to
属性,这个属性的值就是react router要跳转到的地址。如:
import { Link } from 'react-router-dom';
const Nav = () => (
<Link to '/'>Home</Link>
);
to
属性的值可以是一个字符串,也可以是一个location(pathname, hash, state和search)对象。比如:
<Link to{{
pathname: '/me',
search: '?sort=asc',
hash: '#hash',
state: { fromHome: true }
}} />
< Link > 和< NavLink >
NavLink
是Link
的一个子类,在Link组件的基础上增加了绘制组件的样式,比如:
<NavLink to="/me" activeStyle={{SomeStyle}} activeClassName="selected">
My Profile
</NavLink>
使用react-router-dom实现第一个demo
首先,引入必要的组件。比如:Route
和BrowserRouter
。
import { BrowserRouter, Route } from 'react-router-dom';
创建一些组件和一些Html标签。同时我们用react router v4里的Link
和NavLink
组件。
const BaseLayout = () => (
<div className="base">
<header>
<p>React Router v4 Browser Example</p>
<nav>
<ul>
<li><Link ="/">Home</Link></li>
<li><Link ="/about">About</Link></li>
<li><Link ="/me">Profile</Link></li>
<li><Link ="/login">Login</Link></li>
<li><Link ="/register">Register</Link></li>
<li><Link ="/contact">Contact</Link></li>
</ul>
</nav>
</header>
<div className="container">
<Route path="/" exact component={HomePage} />
<Route path="/about" component={AboutPage} />
<Route path="/contact" component={ContactPage} />
<Route path="/login" component={LoginPage} />
<Route path="/register" component={RegisterPage} />
<Route path="/me" component={ProfilePage} />
</div>
<footer>
React Router v4 Browser Example (c) 2017
</footer>
</div>
);
const HomePage = () => <div>This is a Home Page</div>
const LoginPage = () => <div>This is a Login Page</div>
const RegisterPage = () => <div>This is a Register Page</div>
const ProfilePage = () => <div>This is a Profile Page</div>
const AboutPage = () => <div>This is a About Page</div>
const ContactPage = () => <div>This is a Contact Page</div>
写App
组件
const App = () => (
<BrowserRouter>
<BaseLayout />
</BrowserRouter>
)
render(<App />, document.getElementById('root'));
非排他的路由
在上例中,我们在HomePage
组件的路由里使用了属性exact
。
<Route path="/" exact component={HomePage} />
这是因为v4中的路由默认都是非排他的,这一点和v3的实现思路截然不同。如果没有exact
属性,HomePage
组件和其他的组件就会同事绘制在页面上。
如,当用户点了登录连接以后,"/"
和"/login"
都满足匹配条件,对应的登录组件和Home组件就会同时出现在界面上。但是,这不是我们期待的结果,所以我们要给"/"
path加上exact
属性。
现在我们来看看非排他的路由有什么优点。假如我们有一个子菜单组件需要显示在profile页面出现的时候也出现。我们可以简单的修改BasicLayout
来实现。
const BaseLayout = () => (
<div className="base">
<header>
<p>React Router v4 Browser Example</p>
<nav>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li>
<Link to="/me">Profile</Link>
<Route path="/me" component={ProfileMenu} />
</li>
{/*略*/}
</ul>
</nav>
</header>
</div>
);
这样我们就会看到对应于"/me"
路径的组件都绘制出来了。这就是非排他路由的好处。
排他路由
排他路由是react router v3的默认实现。只有第一个匹配的路由对应的组件会被绘制。这一点也可以用react router v4的Switch
组件来实现。在Switch
组件中,只有第一个匹配的路由<Route>
或者<Redirect>
会被绘制:
import { Switch, Route } from 'react-router';
<Switch>
<Route exact path="/" component={HomePage} />
<Route path="/about" component={AboutPage} />
<Route path="me" component={ProfilePage} />
<Route component={NotFound} />
</Switch>
浏览器历史
react router v4中,提供了一个history
对象。这个对象包含了多个api,可以用来操作浏览器历史等。
你也可以在React应用里使用history
对象的方法:
history.push("/my-path")
history.replace("/my-path")
用另外的方法可以写成:
<Link to="/my-path" />
<Redirect to="my-path" />
使用< Redirect >组件实现重定向
无论何时你要重定向到另外一个地址的时候,都可以使用Redirect
组件:
<Redirect to {{
pathname: '/register',
search: '?utm=something',
state: { referrer: someplage.com }
}}>
或者,更为简单的:
<Redirect to="register" />