全篇講解使用react路由插件:react-router
----------------------------------
課程1:搭建項目
git clone https://github.com/reactjs/react-router-tutorial
cd react-router-tutorial
cd lessons/01-setting-up
npm install
npm start
現在可以打開 http://localhost:8080
課程2:創建路由渲染
本質上,React Router是一個組件
render(<Router/>, document.getElementById('app'))
上述這樣寫將沒有任何展示,除非我們配置一個路由。打開 index.js
1. 導入 Router, Route 和 hashHistory (hashHistory 管理路由歷史)
2. 用 Router 組件代替原來的 App 組件
// ...
import { Router, Route, hashHistory } from 'react-router'
render((
<Router history={hashHistory}>
<Route path="/" component={App}/>
</Router>
), document.getElementById('app'))
然後可以在本地查看: http://localhost:8080
添加多個路由,創建兩個新組件:
- modules/About.js
- modules/Repos.js
// modules/About.js
import React from 'react'
export default React.createClass({
render() {
return <div>About</div>
}
})
// modules/Repos.js
import React from 'react'
export default React.createClass({
render() {
return <div>Repos</div>
}
})
現在我們組合他們到App中,並給出對應路由路徑。
// insert into index.js
import About from './modules/About'
import Repos from './modules/Repos'
render((
<Router history={hashHistory}>
<Route path="/" component={App}/>
{/* add the routes here */}
<Route path="/repos" component={Repos}/>
<Route path="/about" component={About}/>
</Router>
), document.getElementById('app'))
現在可以訪問 http://localhost:8080/#/about 和 http://localhost:8080/#/repos
課程3:用 Link 組件導航
你會經常在 App 中使用 Link 組件。Link 相當於你使用 <a> 標籤當做路由一樣。
下面創建幾個 Link 導航
// modules/App.js
import React from 'react'
import { Link } from 'react-router'
export default React.createClass({
render() {
return (
<div>
<h1>React Router Tutorial</h1>
<ul role="nav">
<li><Link to="/about">About</Link></li>
<li><Link to="/repos">Repos</Link></li>
</ul>
</div>
)
}
})
課程4:嵌套路由
把上述建立的兩個組件About和Repos嵌套在App裏面,這樣就可以在App內分享所有路由路徑。
我們只需做兩步:
首先, 把兩個組件的路由作爲App路由的子節點。
// index.js
// ...
render((
<Router history={hashHistory}>
<Route path="/" component={App}>
{/* make them children of `App` */}
<Route path="/repos" component={Repos}/>
<Route path="/about" component={About}/>
</Route>
</Router>
), document.getElementById('app'))
然後,在App組件下渲染路由子節點的組件。(順便加上兩個路由導航,方便查看。)
// modules/App.js
// ...
render() {
return (
<div>
<h1>React Router Tutorial</h1>
{/* 添加導航 */}
<ul role="nav">
<li><Link to="/about">About</Link></li>
<li><Link to="/repos">Repos</Link></li>
</ul>
{/* 添加渲染子節點 */}
{this.props.children}
</div>
)
}
// ...
這樣,點擊導航,就可以看到兩個組件的嵌套路由渲染在 this.props.children 那裏。
react-router 會把頁面構造成這樣:
// 當你訪問 /about
<App>
<About />
</App>
// 當你訪問 /repos
<App>
<Repos />
</App>
課程5:熱點導航
與<a>標籤不同的是,Link 組件如果匹配到當前訪問路徑是它所導航的地址,那麼你可以給它不同的樣式修飾(添加熱點樣式)。
熱點樣式
熱點樣式修飾看起來像內聯樣式,添加 activeStyle 到你的 Link 組件中。
// modules/App.js
<li><Link to="/about" activeStyle={{ color: 'red' }}>About</Link></li>
<li><Link to="/repos" activeStyle={{ color: 'red' }}>Repos</Link></li>
現在被激活的導航鏈接是文字是紅色。
熱點樣式類名
你也可以用樣式類名代替內聯樣式。
// modules/App.js
<li><Link to="/about" activeClassName="active">About</Link></li>
<li><Link to="/repos" activeClassName="active">Repos</Link></li>
引入樣式文件在頁面中。
// index.html
<link rel="stylesheet" href="index.css" />
並在css文件index.css裏寫上樣式。
.active {
color: green;
}
然後刷新一下頁面看效果,不然Webpack沒有編譯,看不到效果。
導航鏈接包裝
如果在網站有很多導航鏈接,我們沒有必要一個一個的去定義並寫出 activeClassName 或者 activeStyle。
只需要創建一個 Link 組件的包裝類就可以了。
比如 創建一個新文件路徑: modules/NavLink.js
// modules/NavLink.js
import React from 'react'
import { Link } from 'react-router'
export default React.createClass({
render() {
return <Link {...this.props} activeClassName="active"/>
}
})
然後在App中的導航,直接用 NavLink 這個包裝類。
// modules/App.js
import NavLink from './NavLink'
// ...
<li><NavLink to="/about">About</NavLink></li>
<li><NavLink to="/repos">Repos</NavLink></li>
這樣效果非常好。
課程6:路由參數
思考一下下面兩個URL:
/repos/reactjs/react-router
/repos/facebook/react
他們兩個可以用一個正則來匹配:
/repos/:userName/:repoName
符號 : 後面的參數,在路由組件中,可以用 this.props.params[name] 來訪問。這裏有兩個參數:userName 和 repoName 可以獲取訪問。
添加帶參數的路由
讓我們瞭解一下 App 如何在 /repos/:userName/:repoName 參數路由下渲染界面。
首先,創建一個新文件 modules/Repo.js 如下:
// modules/Repo.js
import React from 'react'
export default React.createClass({
render() {
return (
<div>
<h2>{this.props.params.repoName}</h2>
</div>
)
}
})
再打開 index.js 添加新路由。
// ...
// import Repo
import Repo from './modules/Repo'
render((
<Router history={hashHistory}>
<Route path="/" component={App}>
<Route path="/repos" component={Repos}/>
{/* 添加新路由 */}
<Route path="/repos/:userName/:repoName" component={Repo}/>
<Route path="/about" component={About}/>
</Route>
</Router>
), document.getElementById('app'))
現在我們加一下路由導航在 Repos.js 裏面。
// Repos.js
import { Link } from 'react-router'
// ...
export default React.createClass({
render() {
return (
<div>
<h2>Repos</h2>
{/* 添加一些路由導航 */}
<ul>
<li><Link to="/repos/reactjs/react-router">React Router</Link></li>
<li><Link to="/repos/facebook/react">React</Link></li>
</ul>
</div>
)
}
})
現在點擊上述兩個導航路由,就能看到 路由參數 repoName 在 Repos組件中 用 this.props.params 獲取展示。也說明了路由參數的應用。
課程7:更多嵌套
如果需要在通用的組件下嵌套展示其它組件,該怎麼做?
首先,嵌套 Repo 路由 在 Repos 路由下,然後在Repos 組件下渲染 子節點 this.props.children。
// index.js
// ...
<Route path="/repos" component={Repos}>
<Route path="/repos/:userName/:repoName" component={Repo}/>
</Route>
// Repos.js
// ...
<div>
<h2>Repos</h2>
<ul>
<li><Link to="/repos/reactjs/react-router">React Router</Link></li>
<li><Link to="/repos/facebook/react">React</Link></li>
</ul>
{/* 將會渲染 `Repo.js` 組件,如果訪問 /repos/:userName/:repoName 路徑 */}
{this.props.children}
</div>
也可以再加一下之前的熱點導航鏈接進來。
// modules/Repos.js
// import it
import NavLink from './NavLink'
// ...
<li><NavLink to="/repos/reactjs/react-router">React Router</NavLink></li>
<li><NavLink to="/repos/facebook/react">React</NavLink></li>
// ...
課程8:首頁路由
當 URL 訪問根路徑 / ,我們希望渲染 Home 組件。先要創建一個 Home 組件,然後討論如何把它關聯到 根路徑 /。
// modules/Home.js
import React from 'react'
export default React.createClass({
render() {
return <div>Home</div>
}
})
有一種可選方案,就是在 App 下如果有子組件頁面,我們就渲染,沒有的話,渲染 Home 組件:
// modules/App.js
import Home from './Home'
// ...
<div>
{/* ... */}
{this.props.children || <Home/>}
</div>
//...
這樣的話,我們要給 Home 組件寫個路由,就像 About 和 Repos 一樣,Home 變成一個大組件一樣。而且訪問所有路徑都會觸發根路由造成很多問題。
現在用另一種方式 添加一個新路由到 index.js
// index.js
// new imports:
// add `IndexRoute` to 'react-router' imports
import { Router, Route, hashHistory, IndexRoute } from 'react-router'
// and the Home component
import Home from './modules/Home'
// ...
render((
<Router history={hashHistory}>
<Route path="/" component={App}>
{/* 把根路由放在這裏 `/` */}
<IndexRoute component={Home}/>
<Route path="/repos" component={Repos}>
<Route path="/repos/:userName/:repoName" component={Repo}/>
</Route>
<Route path="/about" component={About}/>
</Route>
</Router>
), document.getElementById('app'))
現在訪問 根路徑 就可以看到 Home 組件渲染。應該注意的是 IndexRoute 是沒有填寫路徑的,也沒有子節點。不會造成嵌套路由匹配問題。
課程9:首頁鏈接
我們可以這麼寫首頁導航鏈接
// in App.js
// ...
<li><NavLink to="/">Home</NavLink></li>
// ...
也可以用 IndexLink 代替 NavLink 這麼寫:
// App.js
import { IndexLink } from 'react-router'
// ...
<li><IndexLink to="/" activeClassName="active">Home</IndexLink></li>
onlyActiveOnIndex 屬性
當使用 Link 組件的時候,我們可以用 onlyActiveOnIndex 屬性,如果爲 true 的話,代表訪問根路徑的時候纔會激活顯示此鏈接類名修飾。
<li><Link to="/" activeClassName="active" onlyActiveOnIndex={true}>Home</Link></li>
課程10,11略
課程12:自動導航鏈接
自動導航鏈接有兩種方式,一種通過 react-router 提供的 browserHistory ,一種通過組件的上下文環境 context 中的 路由管理對象。
代碼如下:
// modules/Repos.js
import { browserHistory } from 'react-router'
// ...
handleSubmit(event) {
// ...
const path = `/repos/${userName}/${repo}`
browserHistory.push(path)
},
// ...
export default React.createClass({
// ask for `router` from context
contextTypes: {
router: React.PropTypes.object
},
// ...
handleSubmit(event) {
// ...
this.context.router.push(path)
},
// ..
})
關注微信公衆號