react-router
一、基本使用
- 安装
$ npm install -S react-router
备注:我当时install下来是v3.0.0,所以不适用于v4.0.0哦
- 引入
import { Router, Route, hashHistory } from 'react-router'
- 示例
import { Router, Route, hashHistory } from 'react-router';
render((
// hashHistory:表示路由切换是由URL中'/#/'的'#'部分发生hash变化来触发,例: http://localhost:8080/#/
<Router history={ hashHistory }>
// 访问 '/' 路径,component组件 App 就会加载到 document.getElementById('app')
<Route path="/" component={ App }/>
// 访问http://localhost:8080/#/repos时,就会加载component组件 Repos 到 document.getElementById('app')
<Route path="/repos" component={ Repos }/>
<Route path="/about" component={ About }/>
</Router>
), document.getElementById('app'));
二、路由嵌套
1. 方法一:
<Router history='hashHistory'>
<Route path='/' component={ App }>
<Route path='/repos' component={ Repos }/>
<Route path='/about' component={ About }/>
</Route>
</Router>
2. 方法二:
let routes = <Route path="/" component={App}>
<Route path="/repos" component={Repos}/>
<Route path="/about" component={About}/>
</Route>;
<Router routes={routes} history={browserHistory}/>
访问'/repos'时,会先加载App组件,再在App组件内加载Repos组件,结构如下:
<App>
<Repos />
</App>
但是,App组件得这么写:
export default React.createClass({
render() {
return <div>
{this.props.children} // 此处则是用于加载<Repos />组件内容的地方
</div>
}
})
三、path 属性
Route组件的path属性指定路由的匹配规则。这个属性是可以省略的,这样的话,不管路径是否匹配,总是会加载指定组件。
path通配符
<Route path="/hello/:name">
// 匹配 /hello/michael
// 匹配 /hello/ryan
<Route path="/hello(/:name)">
// 匹配 /hello
// 匹配 /hello/michael
// 匹配 /hello/ryan
<Route path="/files/*.*">
// 匹配 /files/hello.jpg
// 匹配 /files/hello.html
<Route path="/files/*">
// 匹配 /files/
// 匹配 /files/a
// 匹配 /files/a/b
<Route path="/**/*.jpg">
// 匹配 /files/hello.jpg
// 匹配 /files/path/to/file.jpg
1. :paramName
:paramName匹配URL的一个部分,直到遇到下一个/、?、#为止。这个路径参数可以通过this.props.params.paramName取出。
2. ()
()表示URL的这个部分是可选的。
3. *
* 匹配任意字符,直到模式里面的下一个字符为止。匹配方式是非贪婪模式。
4. **
** 匹配任意字符,直到下一个/、?、#为止。匹配方式是贪婪模式。
* 路由匹配规则是从上到下执行,一旦发现匹配,就不再匹配其余的规则了,因此,带参数的路径一般要写在路由规则的底部。
例:
<Route path="/comments" ... />
<Route path="/comments" ... /> // no
<Router>
<Route path="/:userName/:id" component={ UserPage }/>
<Route path="/about/me" component={ About }/> // no
</Router>
四、histroy 属性
用来监听浏览器地址栏的变化,并将URL解析成一个地址对象,供 React Router 匹配,有三种值:
- hashHistory
- browserHistory(推荐)
- createMemoryHistory
-
hashHistory
路由将通过URL的hash部分(#)切换,URL的形式类似example.com/#/some/pathimport { hashHistory } from 'react-router' render( <Router history={hashHistory} routes={routes} />, document.getElementById('app') )
-
browserHistory
浏览器的路由就不再通过hash完成了,而显示正常的路径example.com/some/path,背后调用的是浏览器的History API* 使用该方式需要配置服务器,否则会404
- 开发服务器是webpack-dev-server,需要加上 --history-api-fallback 参数
devserver{ historyApiFallback: true // 不跳转,依赖于HTML5 history API ,如果设置为true,所有的跳转将指向index.html }
or
$ webpack-dev-server --history-api-fallback
- node服务,则需要添加以下设置:
// handle every other route with index.html, which will contain // a script tag to your application's JavaScript file(s). app.get('*', function (request, response){ response.sendFile(path.resolve(__dirname, 'public', 'index.html')) });
- nginx服务器,需添加如下配置:
server { //... location / { try_files $uri /index.html; } }
- Apache服务器,首先在项目根目录下创建一个.htaccess文件,添加如下代码:
RewriteBase / RewriteRule ^index\.html$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.html [L]
-
createMemoryHistory
主要用于服务器渲染。它创建一个内存中的history对象,不与浏览器URL互动const history = createMemoryHistory(location)
五、IndexRoute 组件
访问'/'根路径时,默认加载某个组件
<Router>
<Route path="/" component={ App } >
// 设置IndexRoute后 访问'/'路径时,默认加载'Home'组件
<IndexRoute component={ Home }/>
<Route path="accounts" component={ Accounts }/>
<Route path="statements" component={ Statements }/>
</Route>
</Router>
* 注意:IndexRoute组件没有路径参数path
六、跳转 - IndexRedirect 组件
访问'/'根路径时,默认重定向到某个子组件
<Route path="/" component={ App }>
// 设置IndexRedirect后,访问'/'路径时,默认重定向到'welcome'组件
<IndexRedirect to="/welcome" /> // to
<Route path="welcome" component={ Welcome } />
<Route path="about" component={ About } />
</Route>
七、跳转 - Redirect 组件
由访问路由自动跳转到另一个路由
<Route path="inbox" component={ Inbox }>
// 访问/inbox/messages/5,会自动跳转到/messages/5
<Redirect from="messages/:id" to="/messages/:id" /> // to
</Route>
八、跳转 - Link 组件
作用类似于<a>标签,生成一个链接,允许点击后跳转到另一个路由,可以接收Router的状态
render() {
return <div>
<ul role='nav'>
// 点击跳转到 /about
<li><Link to='/about'>About</Link></li> // to
<li><Link to='/repos'>Repos</Link></li>
</ul>
</div>
}
-
activeStyle
用于设定css样式,实现自定义样式<Link to="/about" activeStyle={{color: 'red'}}>About</Link>
-
activeClassName
用于设定class<Link to="/repos" activeClassName="repos">Repos</Link>
九、跳转 - push
可使用浏览器的History API进行路由的跳转,一般用于触发某个元素的事件进行跳转
import { browserHistory } from 'react-router';
browserHistory.push('/some/path');
十、跳转 - IndexLink
用于跳转到跟路由'/',不能直接使用Link。'/'会匹配所有子路由,所以activeStyle和activeClassName会失效,而IndexLink组件会使用路径的精确匹配,才能使用activeClassName
<IndexLink to='/' activeClassNmae='home'> // to
Home
<IndexLink/>
实际等同于:
<Link to='/' activeClassName='home' onlyActiveOnIndex={true}>
Home
</Link>
所以简单使用<IndexLink>就好
十一、表单跳转,按钮跳转
// form
<form onSubmit={this.handleSubmit}>
<input type="text" placeholder="userName"/>
<input type="text" placeholder="repo"/>
<button type="submit">Go</button>
</form>
方法一:push
import { browserHistory } from 'react-router'
// ...
handleSubmit(event) {
event.preventDefault()
const userName = event.target.elements[0].value
const repo = event.target.elements[1].value
const path = `/repos/${userName}/${repo}`
browserHistory.push(path)
},
方法二:context
export default React.createClass({
// ask for `router` from context
contextTypes: {
router: React.PropTypes.object
},
handleSubmit(event) {
// ...
this.context.router.push(path)
},
})
十二、路由钩子
-
onEnter
进入路由时触发
示例:onEnter替代<Redirect>
示例:认证<Route path="inbox" component={Inbox}> <Route path="messages/:id onEnter={({params}, replace) => replace(`/messages/${params.id}`)} /> </Route>
const requireAuth = (nextState, replace) => { if (!auth.isAdmin()) { // Redirect to Home page if not an Admin replace({ pathname: '/' }) } } export const AdminRoutes = () => { return ( <Route path="/admin" component={Admin} onEnter={requireAuth} /> ) }
-
onLeave
离开路由时触发
示例:离开一个路径的时候,跳出一个提示框,要求用户确认是否离开const Home = withRouter( React.createClass({ componentDidMount() { this.props.router.setRouteLeaveHook( this.props.route, this.routerWillLeave ) }, routerWillLeave(nextLocation) { // 返回 false 会继续停留当前页面, // 否则,返回一个字符串,会显示给用户,让其自己决定 if (!this.state.isSaved) return '确认要离开?'; }, }) )