react-router路由实践
Router,hashHistory,Route,browserHistory
首先下载react-router,命令如下:
npm install react-router --save
需要注意的是,react-router更新很快,API也在持续升级,也许你看到市面很多教程,但可能那还是1.x甚至是0.x版本的
首先在App.js写一个简单示例,让你快速的对react-router有印象。
App.js
import React from 'react';
import $ from 'jquery';
import {Router,Route,hashHistory,browserHistory,Redirect,IndexRoute} from 'react-router';
import Home from './Home'; //导航条首页
import About from './About'; //导航条about页
import Work from './Work'; //导航条work页
import me from './me';
import PageNotFound from './PageNotFound';
import Index from './IndexRoute.js';
import Blog from './Blog.js';
class App extends React.Component{
render(){
return(
<div>
<Router history={browserHistory}>
<Route path='/' component={Home}>
<IndexRoute component={Index}/>
<Route path='about' component={About}>
<Route path='me' component={me}/>
</Route>
<Route path='work' component={Work}/>
<Blog path='blog/:title' component={Blog}/>
<Route path='404' component={PageNotFound}/>
<Redirect from='contact' to='about'/>
</Route>
</Router>
</div>
)
}
}
export default App;
history有俩种:
- hashHistory
- browserHistory
hashHistory给我们的路径添加/#/防止浏览器跳转到其他页面,始终拿到的是index.html,不需要服务器支持
browserHistory利用我们的服务器,做实现页面的跳转,不论访问任何路径,都反回index.html,路径看起来美观 正常,但是需要有本地服务支持,如果托管在github,coding等网站上的话用不了 browserHistory和hashHistory不一样,使用browserHistory的时候,浏览器中导航栏的URL就不会出现_k的hash键值对。实际项目中也一般用browserHistory.
这样正常点击路由切换没有问题,但是重新刷新URL就会报找不到路由,这个时候我们在webpack-dev-server启动的时候需要加上参数–history-api-fallback。或者在webpack-dev-server.js文件中加入如下指令,这样就不用 每次启动webpack时输入–history-api-fallback
devServer:{ port:8000, inline:true, historyApiFallback:true },
"scripts": {
"build": "./node_modules/.bin/webpack --config webpack.config.js",
"start": "./node_modules/.bin/webpack-dev-server --config webpack.dev.config.js --inline --content-base . --history-api-fallback"
},
注意:Route可以嵌套Route,
Link
Link是react-router提供的导航组件,可以直接使用进行路由切换
import React from 'react';
import {Link} from 'react-router';
class NavBar extends React.Component{
render(){
let styles={
width:'300px',
float:'left',
marginLeft:'20px'
}
return(
<div style={styles}>
<Link to='/' activeStyle= activeClassName='cool' onlyActiveOnIndex={true}>home</Link><br/>
<Link to='/work' activeStyle= activeClassName='cool'>work</Link><br/>
<Link to='/about' activeStyle= activeClassName='cool'>about</Link>
</div>
)
}
}
export default NavBar;
activeStyle,activeClassName
当前路由被点击处于触发显示状态的时候,我们可以使用activeStyle来给路由设置一些颜色.
import React, { Component } from 'react';
import { Router, Route, browserHistory, Link } from 'react-router';
const Home = () => <div><h1>Home</h1><Links /></div>;
const About = () => <div><h1>About</h1><Links /></div>;
const Contact = () => <div><h1>Contact</h1><Links /></div>;
const Links = () =>
<nav>
<Link activeStyle= to="/">Home</Link>
<Link activeStyle= to="/about">About</Link>
<Link activeStyle= to="/contact">Contact</Link>
</nav>
class App extends Component {
render() {
return (
<Router history={browserHistory}>
<Route path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />
</Router>
);
}
}
export default App;
同理,我们还可以使用activeClassName来将路由激活状态的样式抽取出来。
IndexRoute
IndexRoute即处理页面初始进入时候的组件展示,等路由切换的时候,再根据其他路由规则进行组件的切换展示
import React from 'react';
import $ from 'jquery';
import {Router,Route,browserHistory,IndexRoute} from 'react-router';
import Home from './Home';
import About from './About';
import Work from './Work';
import Index from './IndexRoute.js';
class App extends React.Component{
render(){
return(
<div>
<Router history={browserHistory}>
<Route path='/' component={Home}>
<IndexRoute component={Index}/>
<Route path='about' component={About}/>
<Route path='work' component={Work}/>
</Route>
</Router>
</div>
)
}
}
export default App;
路由变量
刚才展示的是常规的路由,路由中的规则是给定的,现在我们尝试使用路由变量,在组件中获取这个路由的变量,并做相应的组件展示。
import React, { Component } from 'react';
import { Router, Route, hashHistory, Link, IndexRoute } from 'react-router';
import './App.css';
const Message = (props) =>
<div>
<h1>{props.params.message || 'Hello'}</h1>
<Links />
</div>
const Links = () =>
<nav>
<Link to="/">Hello</Link>
<Link to="/yong">Yong</Link>
<Link to="/feng">Feng</Link>
</nav>
class App extends Component {
render() {
return (
<Router history={hashHistory}>
<Route path="/(:message)" component={Message} />
</Router>
);
}
}
export default App;
Route中components参数的高级用法
Route中components中接收的参数不仅仅只是实际的组件,还可以是对象,通过这样的用法,我们可以更灵活的控制组件的展示
import React, { Component } from 'react';
import { Router, Route, hashHistory, Link, IndexRoute } from 'react-router';
import './App.css';
const HomeHeader = () => <h1>HomeHeader</h1>
const HomeBody = () => <h1>HomeBody</h1>
const AboutHeader = () => <h1>AboutHeader</h1>
const AboutBody = () => <h1>AboutBody</h1>
const Container = (props) =>
<div>
{props.header}
{props.body}
<Links />
</div>
const Links = () =>
<nav>
<Link to="/">Hello</Link>
<Link to="/about">About</Link>
</nav>
class App extends Component {
render() {
return (
<Router history={hashHistory}>
<Route path="/" component={Container}>
<IndexRoute components= />
<Route path="about" components= />
</Route>
</Router>
);
}
}
export default App;
使用query获取URL中的参数
我们可以将URL中访问的参数获取,并且应用到组件中
import React, { Component } from 'react';
import { Router, Route, hashHistory, Link, IndexRoute } from 'react-router';
import './App.css';
const Page = (props) =>
<div>
<h1>{props.location.query.message || 'Hello'}</h1>
</div>
class App extends Component {
render() {
return (
<Router history={hashHistory}>
<Route path="/" component={Page} />
</Router>
);
}
}
export default App;
然后在url中输入http://localhost:8080/#/?message=guoyongfeng,页面中就会显示guoyongfeng。
另外,我们还可以在Link组件中设置pathname和query变量
import React, { Component } from 'react';
import { Router, Route, hashHistory, Link, IndexRoute } from 'react-router';
import './App.css';
const Page = (props) =>
<div>
<h1>{props.location.query.message || 'Hello'}</h1>
</div>
const Links = () =>
<nav>
<Link to={/*{ pathname: "/", query: {message: "guoyongfeng"} */}*/ } />
</nav>
class App extends Component {
render() {
return (
<Router history={hashHistory}>
<Route path="/" component={Page} />
</Router>
);
}
}
export default App;
Redirect重定向
import React, { Component } from 'react';
import { Router, Route, hashHistory, Link, Redirect } from 'react-router';
const Home = () => <div><h1>Home</h1><Links /></div>;
const About = () => <div><h1>About</h1><Links /></div>;
const Contact = () => <div><h1>Contact</h1><Links /></div>;
const Links = () =>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Link to="/contact">Contact</Link>
<Link to="/contact-us">Contact US</Link>
</nav>
class App extends Component {
render() {
return (
<Router history={hashHistory}>
<Route path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/contact-us" component={Contact} />
<Redirect from="/contact" to="/contact-us" />
</Router>
);
}
}
export default App;
setRouteLeaveHook路由钩子函数:处理路由切换时的操作
import React, { Component, PropTypes } from 'react';
import { Router, Route, hashHistory, Link } from 'react-router';
class Home extends Component {
componentWillMount(){
this.context.router.setRouteLeaveHook(
this.props.route,
this.routerWillLeave
)
}
routerWillLeave( nextLocation ){
return `页面即将从Home切换到${nextLocation.pathname}`
}
render(){
return <div>
<h1>Home</h1>
<Links />
</div>
}
}
Home.contextTypes = {
router: PropTypes.object.isRequired
};
const Contact = () => <div><h1>Contact</h1><Links /></div>;
const Links = () =>
<nav>
<Link to="/">Home</Link>
<Link to="/contact">Contact</Link>
</nav>
class App extends Component {
render() {
return (
<Router history={hashHistory}>
<Route path="/" component={Home} />
<Route path="/contact" component={Contact} />
</Router>
);
}
}
export default App;
封装的返回主页和返回几层方法
browserHistory.push('/') 返回主页
browserHistory.go(-1) 返回上一级
browserHistory.goBack() 返回主页
同理hashHistory或this.props.router也有此类方法