1. 理解react-router
react的一個插件庫
專門用來實現一個SPA應用
基於react的項目基本都會用到此庫
2. 幾個重要問題
1). SPA應用
單頁Web應用(single page web application,SPA)
整個應用只有一個完整的頁面
點擊頁面中的連接不會刷新頁面, 自己也不會向服務器發請求
當點擊連接時, 只會作頁面的局部更新
數據都須要經過ajax請求獲取, 並在前端異步展示
2). 路由
1. 什麼是路由?
一個路由就是一個映射關係(key:value)
key爲路由路徑, value多是function/component
2. 路由分類
後臺路由: node服務器端路由, value是function, 用來處理客戶端提交的請求並返回一個響應數據
前臺路由: 瀏覽器端路由, value是component, 當請求的是路由path時, 瀏覽器端前沒有發送http請求, 但界面會更新顯示對應的組件
3. 後臺路由
* 註冊路由: router.get(path, function(req, res))
* 當node接收到一個請求時, 根據請求路徑找到匹配的路由, 調用路由中的函數來處理請求, 返回響應數據
* 前端路由
* 註冊路由: <Route path="/about" component={About}>
* 當瀏覽器的hash變爲#about時, 當前路由組件就會變爲About組件
3). 關於url中的#
1. 理解#
'#'表明網頁中的一個位置。其右面的字符,就是該位置的標識符
改變#不觸發網頁重載
改變#會改變瀏覽器的訪問歷史
2. 操做#
window.location.hash讀取#值
window.onhashchange = func 監聽hash改變
3. 學習資源:
阮一峯教程: http://www.ruanyifeng.com/blog/2011/03/url_hash.html
3. react-router的學習資源
github主頁: https://github.com/ReactTraining/react-router
官網教程: https://github.com/reactjs/react-router-tutorial
阮一峯教程: http://www.ruanyifeng.com/blog/2016/05/react_router.html
4. 相關API
1). react-router中的相關組件:
Router: 路由器組件, 用來包含各個路由組件
Route: 路由組件, 註冊路由
IndexRoute: 默認子路由組件
hashHistory: 路由的切換由URL的hash變化決定,即URL的#部分發生變化
Link: 路由連接組件
2). Router: 路由器組件
屬性: history={hashHistory} 用來監聽瀏覽器地址欄的變化, 並將URL解析成一個地址對象,供React Router匹配
子組件: Route
3). Route: 路由組件
屬性1: path="/xxx"
屬性2: component={Xxx}
根路由組件: path="/"的組件, 通常爲App
子路由組件: 子<Route>配置的組件
4). IndexRoute: 默認路由
當父路由被請求時, 默認就會請求此路由組件
5). hashHistory
用於Router組件的history屬性
做用: 爲地址url生成?_k=hash, 用於內部保存對應的state
6). Link: 路由連接
屬性1: to="/xxx"
屬性2: activeClassName="active"
5. react-router的基本使用
1). 下載
npm install react-router --save
2). 定義各個路由組件
1. About.js
import React from 'react'
function About() {
return <div>About組件內容</div>
}
export default About
2. Home.js
import React from 'react'
function Home() {
return <div>Home組件內容2</div>
}
export default Home
3. Repos.js
import React, {Component} from 'react'
export default class Repos extends Component {
render() {
return (
<div>Repos組件</div>
)
}
}
4. App.js
import React, {Component} from 'react'
import {Link} from 'react-router'
export default class App extends Component {
render() {
return (
<div>
<h2>Hello, React Router!</h2>
<ul>
<li><Link to="/about" activeClassName="active">About2</Link></li>
<li><Link to="/repos" activeClassName="active">Repos2</Link></li>
</ul>
{this.props.children}
</div>
)
}
}
3). index.js: 註冊路由, 渲染路由器標籤
import React from 'react'
import {render} from 'react-dom'
import {Router, Route, IndexRoute, hashHistory} from 'react-router'
import App from './modules/App'
import About from './modules/About'
import Repos from './modules/Repos'
import Home from './modules/Home'
render((
<Router history={hashHistory}>
<Route path="/" component={App}>
<IndexRoute component={Home}/>
<Route path="/about" component={About}></Route>
<Route path="/repos" component={Repos}></Route>
</Route>
</Router>
), document.getElementById('app'))
3). 主頁面: index.html
<style>
.active {
color: red;
}
</style>
6. 向路由組件傳遞請求參數
1). repo.js: repos組件下的分路由組件
import React from 'react'
export default function ({params}) {
let {username, repoName} = params
return (
<div>用戶名:{username}, 倉庫名:{repoName}</div>
)
}
2). repos.js
import React from 'react'
import NavLink from './NavLink'
export default class Repos extends React.Component {
constructor(props) {
super(props);
this.state = {
repos: [
{username: 'faceback', repoName: 'react'},
{username: 'faceback', repoName: 'react-router'},
{username: 'Angular', repoName: 'angular'},
{username: 'Angular', repoName: 'angular-cli'}
]
};
this.handleSubmit = this.handleSubmit.bind(this)
}
handleSubmit () {
const repos = this.state.repos
repos.push({
username: this.refs.username.value,
repoName: this.refs.repoName.value
})
this.setState({repos})
this.refs.username.value = ''
this.refs.repoName.value = ''
}
render() {
return (
<div>
<h2>Repos</h2>
<ul>
{
this.state.repos.map((repo, index) => {
const to = `/repos/${repo.username}/${repo.repoName}`
return (
<li key={index}>
<Link to={to} activeClassName='active'>{repo.repoName}</Link>
</li>
)
})
}
<li>
<form onSubmit={this.handleSubmit}>
<input type="text" placeholder="用戶名" ref='username'/> / {' '}
<input type="text" placeholder="倉庫名" ref='repoName'/>{' '}
<button type="submit">添加</button>
</form>
</li>
</ul>
{this.props.children}
</div>
);
}
}
3). index.js: 配置路由
<Route path="/repos" component={Repos}>
<Route path="/repos/:username/:repoName" component={Repo}/>
</Route>
7. 優化Link組件
1). NavLink.js
import React from 'react'
import {Link} from 'react-router'
export default function NavLink(props) {
return <Link {...props} activeClassName="active"/>
}
2). Repos.js
<NavLink to={to}>{repo.repoName}</NavLink>