npm install -S react-router
使用时,路由器Router就是React的一个组件,Router组件自己只是个容器,真正的路由要经过Route组件定义html
import React from 'react'; import ReactDOM from 'react-dom'; import {Router,Route,hashHistory} from 'react-router'; import App from './App.jsx'; import About from './About.jsx'; ReactDOM.render( <Router history={hashHistory}> <Route path="/" component={App}/> <Route path="/about" component={About}/> </Router> , document.getElementById('app'))
Router组件的history属性,用来监听浏览器地址栏的变化,并将URL解析成一个地址对象,供React Router匹配,history一个能够设置三个值react
若是设为browserHistory
,浏览器显示的路径是 example.com/some/path,背后调用的是浏览器的Histtory API.webpack
注意:使用
browserHistory
时须要对服务器改造,不然用户直接向服务器请求某个子路由,会显示找不到网页404错误,若是开发服务器是webpack-dev-server 加上--history-api-fallback参数就能够了,以下在package.json中,其余服务器的配置请参考 https://github.com/ReactTraining/react-router/blob/master/docs/guides/Histories.md#configuring-your-servergit
"scripts": { "dev": "webpack-dev-server --history-api-fallback --hot", "build": "webpack --progress --hide-modules" },
若是设为hashHistory
,路由将经过URL的hash部分#
切换,URL的形式相似 example.com/#/some/path
github
createMemoryHistory
主要用于服务器渲染,它建立一个内存中的history对象,不与浏览器URL互动。web
const history = createMemoryHistory(location)
Route组件还能够嵌套npm
ReactDOM.render( <Router history={browserHistory}> <Route path="/" component={Layout}> <Route path="/index" component={App}/> <Route path="/about" component={About}/> </Route> </Router> , document.getElementById('app'))
上面代码中,用户访问/index或/about时候会先加载Layout组件,而后在Layout组件内部加载App或Abot,为此Layout组件须要加个 {this.props.children}json
import React from "react" export default React.createClass({ render(){ return ( <div> <ul> <li><Link to="index">Index</Link></li> <li><Link to="about">About</Link></li> </ul> {this.props.children} </div> ) } })
上面代码中,{this.props.children} 表明子组件 子路由也能够不写在Router组件里面,单独传入Router组件的routers属性api
import React from 'react'; import ReactDOM from 'react-dom'; import {Router,Route,hashHistory,browserHistory,createMemoryHistory} from 'react-router'; import Layout from './Layout.jsx'; import App from './App.jsx'; import About from './About.jsx'; let routes = <Route component={Layout}> <Route path="/" component={App} /> <Route path="/about" component={About} /> </Route> ReactDOM.render( <Router routes={routes} history={browserHistory}></Router> , document.getElementById('app'))
Route组件的path属性指定路由的匹配规则,这个属性是能够省略,这样的话,无论路径是否匹配,老是会加载指定组件。浏览器
<Route path="home" component={Layout}> <Route path="index" component={App} /> <Route path="about(/:name)" component={About} /> </Route>
上面的例子中当用户访问/home/about/map 的时候,会加载下面的组件
<Layout> <About /> </Layout>
若是省略外层Route的path参数,写成下面的样子
<Route component={Layout}> <Route path="index" component={App} /> <Route path="about/:name" component={About} /> </Route>
如今访问/about/test的时候会加载下面的组件
<Layout> <About /> </Layout>
path属性可使用通配符
<Route path="/hello/:name"> 匹配 /hello/michael <Route path="/hello(/:name)> 匹配 /hello | /hello/test <Route path="/hello/*.*> 匹配 /hello/a.jpg <Route path="/hello/*> 匹配 /hello/ | /hello/test <Route path="/**/*.jpg> 匹配 /hello/a.jpg | /hello/path/to/a.jpg
通配符规则以下
:paramName
匹配URL的一个部分,知道遇到下一个/、?、#
为止,这个路径参数能够经过this.props.params.paramName
取出()
表示URL的这个部分是可选的*
匹配任意字符,知道模式里面的下一个字符为止,匹配方式是非贪婪模式。**
匹配任意字符,知道下一个 /、?、#
为止,匹配方式是贪婪模式。path
属性也可使用相对路径(不以/
开头),匹配时就会相对于父组件的路径,能够参考上一节的例子。嵌套路由若是想摆脱这个规则,可使用绝对路由。 路由匹配规则是从上到下执行,一旦发现匹配,就再也不匹配其他的规则了
<Route path="/hello" component="Hello"> <Route path="/hello" component="About">
上面的代码中,路径/hello
同时匹配两个规则,第二个规则不会生效。 设置路径参数时,须要特别当心这一点。
<Route> <Route path="/:userName/:id" component="Hello"> <Route path="/about/me" component="About"> </Route>
上面的代码中,用户访问 /about/me
的时候永远不会触发第二个路由规则,由于匹配到第一个规则时候就匹配上了,不会向下走了,所以 带参数的路径通常要写在路由规则的底部。
此外,URL的查询字符串 /foo?bar=baz
,能够用 this.props.location.query.bar
获取
IndexRoute组件是为了解决默认状况下根路由的子组件问题的
<Router history={hashHistory}> <Route path="/" component={Layout}> <IndexRoute component={Index} /> <Route path="app" component={App} /> <Route path="about(/:name)" component={About} /> </Route> </Router>
上面代码中,访问根路径 /
会加载Index
组件到Layout
组件的this.props.children
注意:IndexRoute组件没有路径参数path
Redirect组件用于路由的跳转,即用户访问一个路由,会自动跳转到另外一个路由
<Route path="/" component={Layout}> <Redirect from="/foo" to="/404" /> <Route path="404" component={U404} /> <Route path="app" component={App} /> <Route path="about(/:name)" component={About} /> </Route>
如今访问/foo
,就会自动跳转到/404
。
IndexRedirect 组件用于访问根路由的时候,讲用户重定向到某个子路由
<Route path="/" component={Layout}> <IndexRedirect to="/404" /> <Route path="404" component={U404} /> <Route path="app" component={App} /> <Route path="about(/:name)" component={About} /> </Route>
上面代码中,用户访问根路径时,将自动重定向到子路由中
Link
组件用于取代<a>
元素,生成一个连接,容许用户点击后跳转到另外一个路由。它基本上就是<a>
元素的React版本,能够接收Router的状态。
<ul> <li><Link to="/">Index</Link></li> <li><Link to="app">App</Link></li> <li><Link to="about/ggg">About</Link></li> </ul>
若是但愿当前的路由与其余路由有不一样样式,这时可使用Link组件的activeStyle属性
<li><Link to="app" activeStyle={{color:'red'}}>App</Link></li> <li><Link to="about" activeStyle={{color:'red'}}>About</Link></li>
上面代码中,当前页面的连接会红色显示。
另外一种作法是,使用activeClassName
指定当前路由的Class.
<li><Link to="app" activeClassName="active">App</Link></li> <li><Link to="about" activeClassName="active">About</Link></li>
上面代码中,当前页面的连接会红色显示。
在Router
组件以外,导航到路由页面,可使用浏览器的History API,像下面这样写。
import { browserHistory } from 'react-router'; browserHistory.push('/some/path');
或者这样
this.context.router.push('/some/path')
若是连接到根路由/
,不要使用Link组件,而要使用IndexLink
组件。
这是由于对于根路由来讲,activeStyle
和activeClassName
会失效,或者说老是生效,由于/
会匹配任何子路由,而IndexLink
组件会使用路径的精确匹配
<IndexLink to="/" activeStyle={{color:'red'}}>Index</IndexLink>
上面代码中,根路由只会在精确匹配时,才会变成红色
另外一种方法是使用Link
组件的 onlyActiveOnIndex
属性,也能达到一样效果。
<Link to="/" activeStyle={{color:'red'}} onlyActiveOnIndex={true}>Index</Link>
实际上,IndexLink
就是对Link组件的onlyActiveOnIndex属性的包装
每一个路由都有Enter和Leave钩子,用户进入或离开该路由时触发。
<Route path="/app" component={App} onEnter={beforeRouter} onLeave={afterRouter} />
上面的例子中,用户进入/app
的时候会触发onEnter
钩子,用户离开/app
的时候会触发onLeave
钩子,详细例子请看下面
import React from 'react'; import ReactDOM from 'react-dom'; import {Router,Route,IndexRoute,hashHistory} from 'react-router'; import Layout from './Layout.jsx'; import App from './App.jsx'; import Index from './Index.jsx'; import About from './About.jsx'; import NotFound from './NotFound.jsx'; const beforeRouter = (nextState,replace)=>{ console.log("beforeRouter",nextState,replace) } const afterRouter = (nextState,replace)=>{ console.log("afterRouter",nextState,replace) } ReactDOM.render( <Router history={hashHistory}> <Route path="/" component={Layout}> <IndexRoute component={Index} /> <Route path="app" component={App} onEnter={beforeRouter} onLeave={afterRouter} /> <Route path="about(/:name)" component={About} /> <Route path="*" component={NotFound} /> </Route> </Router> , document.getElementById('app'))