首先,在該項目開始之前碍脏,還請大家能夠先下載一個項目腳手架潭辈。本教程基于該腳手架進(jìn)行開發(fā)
Router,hashHistory,Route
首先下載react-router
npm install react-router --save
需要注意的是,react-router更新很快忘晤,API也在持續(xù)升級旅赢,也許你看到市面很多教程齿桃,但可能那還是1.x甚至是0.x版本的。
我們首先在App.jsx寫一個簡單示例煮盼,讓你快速的對react-router有印象短纵。
代碼清單:app/container/App/App.jsx
import React, { Component } from 'react';
import { Router, Route, hashHistory } from 'react-router';
const Home = () => <div><h1>Home</h1></div>;
const About = () => <div><h1>About</h1></div>;
const Contact = () => <div><h1>Contact</h1></div>;
class App extends Component {
render() {
return (
<Router history={hashHistory}>
<Route path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />
</Router>
);
}
}
export default App;
Link
Link是react-router提供的導(dǎo)航組件,可以直接使用進(jìn)行路由切換
代碼清單:app/container/App/App.jsx
import React, { Component } from 'react';
import { Router, Route, hashHistory, 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 to="/">Home</Link>
<Link to="/about">About</Link>
<Link to="/contact">Contact</Link>
</nav>
class App extends Component {
render() {
return (
<Router history={hashHistory}>
<Route path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />
</Router>
);
}
}
export default App;
browserHistory
browserHistory和hashHistory不一樣孕似,使用browserHistory的時候踩娘,瀏覽器中導(dǎo)航欄的URL就不會出現(xiàn)_k的hash鍵值對刮刑。實際項目中也一般用browserHistory.
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 to="/">Home</Link>
<Link to="/about">About</Link>
<Link 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;
這樣正常點擊路由切換沒有問題喉祭,但是重新刷新URL就會報找不到路由,這個時候我們在webpack-dev-server啟動的時候需要加上參數(shù)--history-api-fallback
雷绢。
activeStyle,activeClassName
當(dāng)前路由被點擊處于觸發(fā)顯示狀態(tài)的時候泛烙,我們可以使用activeStyle來給路由設(shè)置一些顏色
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={{color: 'red'}} to="/">Home</Link>
<Link activeStyle={{color: 'red'}} to="/about">About</Link>
<Link activeStyle={{color: 'red'}} 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來將路由激活狀態(tài)的樣式抽取出來翘紊。
我們在App.css寫一個樣式蔽氨,代碼清單:app/containers/App/App.jsx
.active {
color: red;
}
然后修改App.jsx
import React, { Component } from 'react';
import { Router, Route, browserHistory, Link } from 'react-router';
import './App.css';
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 activeClassName="active" to="/">Home</Link>
<Link activeClassName="active" to="/about">About</Link>
<Link activeClassName="active" 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;
路由嵌套
剛才講的是簡單路由的切換,但實際應(yīng)用中帆疟,路由是分多個層級的鹉究。幸運(yùn)的是,我們可以使用react-router的路由嵌套來清晰的管理路由和組件之間的切換展示踪宠。
import React, { Component } from 'react';
import { Router, Route, browserHistory, Link } from 'react-router';
import './App.css';
const Home = (props) =>
<div>
<h1>Home</h1>
<Links />
{props.children}
</div>
const About = (props) =>
<div>
<h1>About</h1>
{props.children}
</div>
const Contact = () =>
<div>
<h1>Contact</h1>
</div>
const Links = () =>
<nav>
<Link activeClassName="active" to="/">Home</Link>
<Link activeClassName="active" to="/about">About</Link>
<Link activeClassName="active" to="/about/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} />
</Route>
</Route>
</Router>
);
}
}
export default App;
IndexRoute
IndexRoute即處理頁面初始進(jìn)入時候的組件展示自赔,等路由切換的時候,再根據(jù)其他路由規(guī)則進(jìn)行組件的切換展示柳琢。
import React, { Component } from 'react';
import { Router, Route, browserHistory, Link, IndexRoute } from 'react-router';
import './App.css';
const Home = (props) =>
<div>
<h1>Home</h1>
<Links />
{props.children}
</div>
const About = () =>
<div>
<h1>About</h1>
</div>
const Contact = () =>
<div>
<h1>Contact</h1>
</div>
const Links = () =>
<nav>
<Link activeClassName="active" to="/">Home</Link>
<Link activeClassName="active" to="/contact">Contact</Link>
</nav>
class App extends Component {
render() {
return (
<Router history={browserHistory}>
<Route path="/" component={Home}>
<IndexRoute component={About} />
<Route path="contact" component={Contact} />
</Route>
</Router>
);
}
}
export default App;
路由變量
剛才展示的是常規(guī)的路由绍妨,路由中的規(guī)則是給定的润脸,現(xiàn)在我們嘗試使用路由變量,在組件中獲取這個路由的變量他去,并做相應(yīng)的組件展示毙驯。
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參數(shù)的高級用法
Route中components中接收的參數(shù)不僅僅只是實際的組件,還可以是對象灾测,通過這樣的用法爆价,我們可以更靈活的控制組件的展示。
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={{ header:HomeHeader, body:HomeBody }} />
<Route path="about" components={{ header:AboutHeader, body:AboutBody }} />
</Route>
</Router>
);
}
}
export default App;
使用query獲取URL中的參數(shù)
我們可以將URL中訪問的參數(shù)獲取媳搪,并且應(yīng)用到組件中允坚。
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=wn
,頁面中就會顯示wn蛾号。
另外稠项,我們還可以在Link組件中設(shè)置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路由鉤子函數(shù):處理路由切換時的操作
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;
最后
總的來說,react-router的學(xué)習(xí)難度不高鲜结,但是會有不同版本間API升級的坑展运,后續(xù)大家持續(xù)關(guān)注,或是使用某一個自己熟悉的react-router版本精刷。
附上我的github地址
最后拗胜,希望這篇博客對大家有所幫助(如果是,請盡情star哦怒允,??)埂软,歡迎提出您的寶貴建議~