發表於:2014-09-20express
本文已過期,推薦閱讀最新的 React Router v0.13.3 版使用指南api
本文已過期,推薦閱讀最新的 React Router v0.13.3 版使用指南瀏覽器
本文已過期,推薦閱讀最新的 React Router v0.13.3 版使用指南react-router
在構建一個複雜的頁面時,給不一樣的操做賦予不一樣的路由(route)是一個很好的實踐。對於習慣Backbone的人來講Backbone.Router
就是一個很方便的route-action
映射模塊,那麼在React中應該怎樣增長路由呢?雖然也可使用Backbone的解決方案,可是ReactRouter或許是一個更符合React思想的路由組件。ide
ReactRouter(github地址)是由Ryan Florence開發的應用於ReactJS的路由組件,它經過定義ReactJS組件<Routes>
及相關子組件來實現頁面路由的映射、參數的解析和傳遞。若是你熟悉ember.js
,你會發現它處理路由的方式和ember的思想是一致的。函數
一個最基本的頁面,菜單有「圖書」和「電影」兩個選項,點擊「圖書」顯示圖書列表(連接變爲/books),點擊「電影」顯示電影列表(連接變爲/movies)。
var ReactRouter = require('react-router'); var Routes = ReactRouter.Routes; var Route = ReactRouter.Route; //定義整個頁面的路由結構 var routes = ( <Routes location="hash"> <Route path="/" handler={App}> <Route path="books" name="bookList" handler={Books}/> <Route path="movies" name="movieList" handler={Movies}/> </Route> </Routes>);
這樣就定義了包含兩條路由規則的路由,一條指向 /books,一條指向 /movies。(嚴格來講應該是三條路由,還有一個指向 / 的路由)
<Routes>
組件接受一個名爲 location 的 props,這是用來定義用何種前端技術實現路由,可選參數爲hash或histroy。hash表示經過改變location.hash更新頁面連接,而histroy表示使用history.pushState來更新連接。若是不考慮兼容IE8,能夠選擇history。
<Route>
組件是ReactRouter的核心組件,經過它來定義路由對應的路徑,處理這條路由的組件(handler)等等。其中path屬性是指這條路由對應的路徑,好比
<Route path="books" name="bookList" handler="Books"/>
點擊後瀏覽器中的路徑就會變爲 http://你的網址/#/books
。
而handler是指當這條路由被觸發時該渲染哪一個組件,其中Books
就是一個React組件。之因此把 name 放在最後講,是由於 name 是用在使用路由的時候起做用。
上面咱們定義了整個頁面的路由規則,但總須要點擊一個什麼連接才能觸發這個路由吧,下面咱們就來加上這麼一個觸發器
,同時看看 name 什麼用。
//在上述代碼的基礎上 var Link = ReactRouter.Link; var App = React.createClass({ render: function(){ return ( <div className="main"> <nav> <Link to="bookList">圖書</Link> <Link to="moviewList">電影</Link> </nav> <div className="content"> <this.props.activeRouteHandler/> </div> </div> ); } }; //routes在上述代碼中已定義 React.renderComponent(routes, document.body);
在上述代碼中咱們新require了一個React組件Link
,這就是咱們路由的觸發器
,你能夠把它理解爲高級版的<a href="#你的hash">連接文字</a>
。注意咱們定義的Link
中有一個 to 屬性,這就是對應了以前定義的路由中<Route>
組件的 name 屬性。好比
<Link to="bookList">圖書</Link>
點擊後就會觸發
<Route path="books" name="bookList" handler="Books"/>
從而致使Books
這個React組件被渲染。ReactRouter還作了一個很貼心的功能,當點擊Link觸發對應的路由後,Link
自己還會被添加 active 的className,方便你對當前激活的菜單項添加樣式。(效果見DEMO,className默認是 active,能夠經過傳 props 改變)
問題又來了,哪一行代碼定義了該渲染哪一個組件呢?注意咱們的 App
組件中的<this.props.activeRouteHandler/>
,這就是ReactRouter爲咱們自動添加的當前 active 的handler,當點擊 bookList
時,activeRouteHandler就是Books組件。
另外還須要注意一點,和咱們習慣中的React渲染方式不一樣,最終渲染到DOM上的組件並非常規的React組件,而是咱們定義的routes
。注意React.renderComponent(routes, document.body);
這一行。
把玩一下DEMO你會發現,雖然路由起做用了(因爲jsfiddle沙盒的限制,路由的改變並無反映到瀏覽器的地址欄中),可是在默認狀態下除了兩個菜單項啥都沒有渲染,這和咱們的預期不符。
若是你想默認就顯示全部圖書,即默認渲染Books
這個React組件,那麼你須要引入一個新的ReactRouter組件Redirect
。
var Redirect = ReactRouter.Redirect; var routes = ( <Routes location="hash"> <Route path="/" handler={App}> <Route path="books" name="bookList" handler={Books}/> <Route path="movies" name="movieList" handler={Movies}/> <Redirect to="bookList"/> </Route> </Routes>);
和Link
相似,Redirect
也有 to 屬性,這個屬性定義了重定向的地址。咱們的routes
更新後,當訪問當前頁面時(即訪問 / 時),會自動跳轉到 /books。
若是你不想默認顯示圖書或電影,而是另外一個組件,好比歡迎信息什麼的,可使用DefaultRoute
。
var DefaultRoute = ReactRouter.DefaultRoute; var routes = ( <Routes location="hash"> <Route path="/" handler={App}> <Route path="books" name="bookList" handler={Books}/> <Route path="movies" name="movieList" handler={Movies}/> <DefaultRoute handler={Welcome}/> </Route> </Routes>);
這樣在訪問 / 時,默認會渲染Welcome
組件,注意這個時候兩個菜單項都沒有被激活(即沒有 active 的className),除非你點擊「圖書」或「電影」。
業務邏輯更復雜了,如今除了點擊「圖書」顯示圖書列表,點擊「電影」顯示電影列表外,點擊某一本圖書(或某一部電影)還要顯示對應的詳情。
首先更新路由對象
var routes = ( <Routes location="hash"> <Route path="/" handler={App}> <Route path="books" name="bookList" handler={Books}> <Route path=":bookId" name="book" handler={Book}/> </Route> <Route path="movies" name="movieList" handler={Movies}> <Route path=":movieId" name="movie" handler={Movie}/> </Route> <DefaultRoute handler={Welcome}/> </Route> </Routes>);
和以前的路由對象相似,須要嵌套的路由直接進行嵌套便可(徹底就是字面意思嘛),可是注意到咱們的<Route>
的path變成了一個奇怪的形式,「:bookId」和「:movieId」是什麼意思?熟悉express
的同窗應該對這樣的路由形式不會陌生,這定義了路由接受的一個參數,簡單的說 /moview/:movieId 定義了一個規則,當訪問 /moviews/123 的時候,程序會自動把 123 提取出來當作名爲 movieId 的參數。
詳細的介紹見路由匹配規則。
既然咱們的路由更新了,那麼對應的 handler 也應該進行更新。首先給Books
和Movies
這兩個組件在render時添加<this.props.activeRouteHandler/>
,而後再新建顯示單個圖書和單個電影的React組件Book
及Movie
。
注意在渲染單個圖書或電影的組件中,咱們能夠經過this.props.params
來提取經過路由傳進來的參數(效果見DEMO)。
另外還要注意一點,正如你在DEMO中看到的,嵌套的路由對應的Link
對象(即視覺上的菜單項)會所有被添加 active 的className,當你查看某一本書的詳情時,書名及圖書菜單都處於高亮狀態,一條龍高亮。
這裏還有另一個問題,若是咱們想點擊某本書的時候再也不顯示圖書列表而是隻顯示菜單和圖書詳情該怎麼辦呢?咱們再對路由對象進行小小的改動。
var routes = ( <Routes location="hash"> <Route path="/" handler={App}> <Route path="books" name="bookList" handler={BookRoute}> <Route path=":bookId" name="book" handler={Book}/> <DefaultRoute handler={Books}/> </Route> <Route path="movies" name="movieList" handler={MovieRoute}> <Route path=":movieId" name="movie" handler={Movie}/> <DefaultRoute handler={Movies}/> </Route> <DefaultRoute handler={Welcome}/> </Route> </Routes>);
首先咱們修改了本來顯示圖書列表及電影列表的handler,將它們改成新的React組件BookRoute
及MovieRoute
,這兩個組件的功能就是渲染 this.props.activeHandler
。
其次咱們將本來的列表當作<DefaultRoute>
渲染,這樣就能實現點擊單條信息的時候再也不顯示列表了。不過這樣就須要新增長兩個傀儡handler,不知道你們有沒有更好的辦法實現。
以上基本覆蓋了SPA中對於路由使用的大多數use case,除了上述功能外,ReactRouter還提供了用於獲取當前active路由的mixin ActiveState
,以及其它實用的工具函數及方法,具體請參考其 API 文檔。
最後還有個小內幕,React的核心做者之一也參與了ReactRouter的開發,所以看來ReactRouter仍是頗有潛力的!
本文已過期,推薦閱讀最新的 React Router v0.13.3 版使用指南
本文已過期,推薦閱讀最新的 React Router v0.13.3 版使用指南
本文已過期,推薦閱讀最新的 React Router v0.13.3 版使用指南
© 2014 undefined
Powered by Ghost
Theme by undefinedblog