React-router 初學(xué)者的14個lessons

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/#/abouthttp://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> ) }})

訪問:http://localhost:8080

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

Paste_Image.png

那么可以使用以下方式保存路由

Paste_Image.png

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ā)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末啼辣,一起剝皮案震驚了整個濱河市啊研,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鸥拧,老刑警劉巖党远,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異富弦,居然都是意外死亡沟娱,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門腕柜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來济似,“玉大人,你說我怎么就攤上這事盏缤∨榇溃” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵唉铜,是天一觀的道長台舱。 經(jīng)常有香客問我,道長潭流,這世上最難降的妖魔是什么竞惋? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任柜去,我火速辦了婚禮,結(jié)果婚禮上拆宛,老公的妹妹穿的比我還像新娘嗓奢。我一直安慰自己,他們只是感情好胰挑,可當(dāng)我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布蔓罚。 她就那樣靜靜地躺著,像睡著了一般瞻颂。 火紅的嫁衣襯著肌膚如雪豺谈。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天贡这,我揣著相機與錄音茬末,去河邊找鬼。 笑死盖矫,一個胖子當(dāng)著我的面吹牛丽惭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播辈双,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼责掏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了湃望?” 一聲冷哼從身側(cè)響起换衬,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎证芭,沒想到半個月后瞳浦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡废士,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年叫潦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片官硝。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡矗蕊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出氢架,到底是詐尸還是另有隱情傻咖,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布达箍,位于F島的核電站没龙,受9級特大地震影響铺厨,放射性物質(zhì)發(fā)生泄漏缎玫。R本人自食惡果不足惜硬纤,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望赃磨。 院中可真熱鬧筝家,春花似錦、人聲如沸邻辉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽值骇。三九已至莹菱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間吱瘩,已是汗流浹背道伟。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留使碾,地道東北人蜜徽。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像票摇,于是被迫代替她去往敵國和親拘鞋。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容