React-router路由實踐

首先,在該項目開始之前碍脏,還請大家能夠先下載一個項目腳手架潭辈。本教程基于該腳手架進(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哦怒允,??)埂软,歡迎提出您的寶貴建議~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市纫事,隨后出現(xiàn)的幾起案子勘畔,更是在濱河造成了極大的恐慌,老刑警劉巖丽惶,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件炫七,死亡現(xiàn)場離奇詭異,居然都是意外死亡钾唬,警方通過查閱死者的電腦和手機(jī)万哪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抡秆,“玉大人奕巍,你說我怎么就攤上這事∪迨浚” “怎么了的止?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長乍桂。 經(jīng)常有香客問我冲杀,道長效床,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任权谁,我火速辦了婚禮剩檀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘旺芽。我一直安慰自己沪猴,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布采章。 她就那樣靜靜地躺著运嗜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪悯舟。 梳的紋絲不亂的頭發(fā)上担租,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天,我揣著相機(jī)與錄音抵怎,去河邊找鬼奋救。 笑死,一個胖子當(dāng)著我的面吹牛反惕,可吹牛的內(nèi)容都是我干的尝艘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼姿染,長吁一口氣:“原來是場噩夢啊……” “哼背亥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起悬赏,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤狡汉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后舷嗡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體轴猎,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嵌莉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年进萄,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锐峭。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡中鼠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出沿癞,到底是詐尸還是另有隱情援雇,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布椎扬,位于F島的核電站惫搏,受9級特大地震影響具温,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜筐赔,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一铣猩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧茴丰,春花似錦达皿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至汰规,卻和暖如春汤功,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背溜哮。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工冤竹, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人茬射。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓鹦蠕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親在抛。 傳聞我的和親對象是個殘疾皇子钟病,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,055評論 2 355

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