Lesson1
1、首先確保安裝了Node.js和npm依賴包管理工具
2椰于、在git上克隆官方示例程序
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
就可以在瀏覽器看見: "Hello React Router"
打開modules/App.js缠导,更改里面內(nèi)容僻造,可以看到瀏覽器上的內(nèi)容隨時變化!
Lesson2 : rendering a router
1竹挡、打開index.js
首先import Router立膛、Route和hashHistory宝泵,然后render Reouter替換原來的App組件。這是由于:React Router 是一個組件框往。Router 本身是一個容器椰弊,真正的路由都要由Route去定義瓤鼻。
// ...
import { Router, Route, hashHistory } from 'react-router'
render(( <Router history={hashHistory}>
<Route path="/" component={App}/>
</Router>), document.getElementById('app'))
上面訪問的路由為“/”茬祷,組件是App。路由的切換由URL得hash變化決定耐朴,即URL的#部分發(fā)生變化盹憎。
2、添加Scene
.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> }})
把場景添加到路由里面
// 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'))
現(xiàn)在訪問: http://localhost:8080/#/about 和 http://localhost:8080/#/repos
Lesson3 Navigating with Link
Link類似于之前用過的<a/>標(biāo)簽
// 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> ) }})
lesson4 嵌套的路由
這個功能可以做出類似Nav的功能镰吵,Route里面可以嵌套多個Route
// 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>
{/* add this */}
{this.props.children}
</div>
) }
則UI結(jié)構(gòu)如下:
<App>
<About/>
</App>
<App>
<Repos/>
</App>
Lesson 5 Active Links
通過行內(nèi)樣式表改變Link的樣式:
// modules/App.js
<li><Link to="/about" activeStyle={{ color: 'red' }}>About</Link></li>
<li><Link to="/repos" activeStyle={{ color: 'red' }}>Repos</Link></li>
也可以添加className在css文件中設(shè)置樣式
// modules/App.js
<li><Link to="/about" activeClassName="active">About</Link></li>
<li><Link to="/repos" activeClassName="active">Repos</Link></li>
創(chuàng)建css文件疤祭,并在index.html中引入
// index.html
<link rel="stylesheet" href="index.css" />
我們不用為每個Link都添加activeClassName勺馆,這里我們使用一個spread operator
創(chuàng)建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"/>
}
})
在modules/App.js中這樣寫:
// modules/App.js
import NavLink from './NavLink'
<li><NavLink to="/about">About</NavLink></li>
<li><NavLink to="/repos">Repos</NavLink></li>
Lesson 6 URL Params
1侨核、添加一個帶參數(shù)的路由
建立一個文件:modules/Repo.js
// modules/Repo.js
import React from 'react'
export default React.createClass({
render() {
return (
<div> <h2>{this.props.params.repoName}</h2> </div>
)
}})
2搓译、在index.js里面添加新路由
// import Repo
import Repo from './modules/Repo'
render((
<Router history={hashHistory}>
<Route path="/" component={App}>
<Route path="/repos" component={Repos}/>
{/* add the new route */}
<Route path="/repos/:userName/:repoName" component={Repo}/>
<Route path="/about" component={About}/>
</Route>
</Router>), document.getElementById('app'))
3些己、在Repo.js里面添加跳轉(zhuǎn)的Link
// Repos.js
import { Link } from 'react-router'
export default React.createClass({
render() {
return (
<div>
<h2>Repos</h2>
{/* add some links */}
<ul>
<li><Link to="/repos/reactjs/react-router">React Router</Link></li>
<li><Link to="/repos/facebook/react">React</Link></li>
</ul>
</div> )
}})
附:path屬性可以匹配通配符
<Route path="/hello/:name">
:paramName 匹配URL的一個部分,知道遇到下一個/涯冠、功偿?往堡、#為止共耍。路徑參數(shù)可以通過this.props.params.paramName獲取
// 匹配 /hello/michael
// 匹配 /hello/ryan
<Route path="/hello(/:name)">
()表示URL的這個部分是可選的
// /hello
// /hello/micale
// /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
路由匹配規(guī)則是從上到下執(zhí)行种呐,一旦發(fā)現(xiàn)匹配爽室,就不再匹配其余的規(guī)則了。
Lesson 7 更多的嵌套
1嘿架、將Repo的路由放進Repos的路由
//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>
{/* will render Repo.js
when at /repos/:userName/:repoName */} #{this.props.children}
</div>
2眶明、添加NavLink
// modules/Repos.js
import NavLink from './NavLink'
<li><NavLink to="/repos/reactjs/react-router">React Router</NavLink></li>
<li><NavLink to="/repos/facebook/react">React</NavLink></li>
Lesson 8 Index Routes
當(dāng)我們訪問/在app里出現(xiàn)了一個空白搜囱,我們想讓他渲染一個Home的component
IndexRoute顯示指定Home是根路由的子組件柑土,即指定默認(rèn)情況下加載的子組件稽屏。IndexRoute組件沒有路徑參數(shù)path
//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>
添加IndexRoute
// index.js
import { Router, Route, hashHistory, IndexRoute } from 'react-router'
import Home from './modules/Home'
render((
<Router history={hashHistory}>
<Route path="/" component={App}>
{/* add it here, as a child of /
*/}
<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'))
IndexRoute沒有path 坛增,
Lesson 9 Index Links
添加可以返回Home的方法收捣,IndexLink
//App.js
import { IndexLink } from 'react-router'
<li><IndexLink to="/" activeClassName="active">Home</IndexLink></li>
使用onlyActiveOnIndex Property
<li><Link to="/" activeClassName="active" onlyActiveOnIndex={true}>Home</Link></li>
或
<li><NavLink to="/" onlyActiveOnIndex={true}>Home</NavLink></li>
Lesson 10 Clean URLs with Browser History
配置瀏覽器歷史
//index.js
// bring in browserHistory
instead of hashHistory
import { Router, Route, browserHistory, IndexRoute } from 'react-router'
render((
<Router history={browserHistory}>
{/* ... */}
</Router>
), document.getElementById('app'))
點擊鏈接罢艾,然后刷新尽纽,會得到
Cannot GET /repos
這是因為服務(wù)器端配置的原因弄贿,目前的服務(wù)器不知道如何處理URL
在package.json中添加:
"start": "webpack-dev-server --inline --content-base . --history-api-fallback"
同時要將我們的文件引用,相對路徑為絕對路徑
//index.html
<link rel="stylesheet" href="/index.css">
<script src="/bundle.js"></script>
重啟服務(wù)器:npm start
Lesson 11 Production-ish Server
Webpack dev server 不是生產(chǎn)模式的服務(wù)器看疙,下面配置生產(chǎn)模式下的服務(wù)器
安裝依賴模塊:
npm install express if-env compression --save
更新package.json
"scripts": {
"start": "if-env NODE_ENV=production && npm run start:prod || npm run start:dev",
"start:dev": "webpack-dev-server --inline --content-base . --history-api-fallback",
"start:prod": "webpack && node server.js"
},
此時的腳本說明能庆,如果運行npm start 啟動服務(wù)器,如果在生產(chǎn)環(huán)境下執(zhí)行start:prod弥搞,如果不是攀例,執(zhí)行start:dev
在根目錄下創(chuàng)建server.js
//server.js
var express = require('express')
var path = require('path')
var compression = require('compression')
var app = express()
// serve our static stuff like index.css
app.use(express.static(__dirname))
// send all requests to index.html so browserHistory in React Router works
app.get('*', function (req, res) {
res.sendFile(path.join(__dirname, 'index.html'))
})
var PORT = process.env.PORT || 8080
app.listen(PORT, function() {
console.log('Production Express server running at localhost:' + PORT)
})
現(xiàn)在運行:NODE_ENV=production npm start
現(xiàn)在就有了生產(chǎn)環(huán)境下的app
此時運行:http://localhost:8080/package.json就可以獲得json文件的內(nèi)容粤铭,讓我們重新更新文件的路徑來解決這個問題
創(chuàng)建一個public的文件夾杂靶,并且把index.html 和 index.css文件放進去
1、更新server.js指向正確的路徑:
// server.js
app.use(express.static(path.join(__dirname, 'public')))
app.get('*', function (req, res) {
res.sendFile(path.join(__dirname, 'public', 'index.html'))
})
2垛吗、更新webpack編譯時的輸出路徑
// webpack.config.js
output: {
path: 'public',
}
3怯屉、在服務(wù)器啟動腳本中饵沧,添加該路徑
"start:dev": "webpack-dev-server --inline --content-base public --history-api-fallback",
4、添加一些代碼
// webpack.config.js
var webpack = require('webpack')
module.exports = {
//...
plugins: process.env.NODE_ENV === 'production' ? [ new #webpack.optimize.DedupePlugin(), new #webpack.optimize.OccurrenceOrderPlugin(), new #webpack.optimize.UglifyJsPlugin() ] : [],
//...
}
在express中添加conpression
// server.js
var compression = require('compression')
var app = express()
// must be first!
app.use(compression())
現(xiàn)在我們可以在生產(chǎn)模式下啟動服務(wù)器了
NODE_ENV=production npm start
Lesson 12 Navigating Programatically
之前使用的都是Link進行路由的跳轉(zhuǎn),而實際使用更多的使用表單提交锁右,按鈕點擊來進行路由的切換
在Repos創(chuàng)建一個表單提交
// modules/Repos.js
那么可以使用以下方式保存路由
Lesson 13 服務(wù)器端渲染
Lesson 14 結(jié)束語
附:組件介紹
1、Redirect組件:<Redirect>用于路由的跳轉(zhuǎn)码泞,即訪問一個路由狼犯,就會自動跳轉(zhuǎn)到另一個路由.
<Route path="inbox" component={Inbox}>
{/* 從 /inbox/messages/:id 跳轉(zhuǎn)到 /messages/:id */}
<Redirect from="messages/:id" to="/messages/:id" />
</Route>
訪問/inbox/message/5,會自動跳到/messages/5
2、IndexRedirect 組件
訪問根路由的時候宋舷,將用戶重定向到某個子組件。
3祝蝠、Link 組件取代<a>標(biāo)簽音诈,
4、IndexLink 如果連接到根路由不要使用Link要使用IndexLink(使用路由的精確匹配)
5绎狭、history屬性
Router的history屬性監(jiān)聽瀏覽器地址的變化细溅,并將URL解析為一個地址對象,供React Router 匹配
6儡嘶、表單處理:Link組件用于正常的用戶點擊跳轉(zhuǎn)喇聊,但有時候還需要表單跳轉(zhuǎn)、點擊按鈕跳轉(zhuǎn)蹦狂。
有兩種方案:1、使用browserHistory.push
2鸥咖、使用context對象
7燕鸽、路由的鉤子
每個路由都有Enter和Leave的鉤子,當(dāng)用戶進入或者離開該路由時觸發(fā)