undefined
- 首頁
- 作品
- 關于
- 内容
everything starts & ends
ReactRouter 使用指南
發表于:2014-09-20
本文已過時,推薦閱讀最新的 React Router v0.13.3 版使用指南
本文已過時,推薦閱讀最新的 React Router v0.13.3 版使用指南
本文已過時,推薦閱讀最新的 React Router v0.13.3 版使用指南
在建構一個複雜的頁面時,給不同的操作賦予不同的路由(route)是一個很好的實踐。對于習慣Backbone的人來說
Backbone.Router
就是一個很友善的
route-action
映射子產品,那麼在React中應該怎樣增加路由呢?雖然也可以使用Backbone的解決方案,但是ReactRouter或許是一個更符合React思想的路由元件。
ReactRouter(github位址)是由Ryan Florence開發的應用于ReactJS的路由元件,它通過定義ReactJS元件
<Routes>
及相關子元件來實作頁面路由的映射、參數的解析和傳遞。如果你熟悉
ember.js
,你會發現它處理路由的方式和ember的思想是一緻的。
快速上手
一個最基本的頁面,菜單有「圖書」和「電影」兩個選項,點選「圖書」顯示圖書清單(連結變為/books),點選「電影」顯示電影清單(連結變為/movies)。
DEMO
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" target="_blank" rel="external nofollow" >連結文字</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
進階使用
把玩一下DEMO你會發現,雖然路由起作用了(由于jsfiddle沙盒的限制,路由的改變并沒有反映到浏覽器的位址欄中),但是在預設狀态下除了兩個菜單項啥都沒有渲染,這和我們的預期不符。
Redirect
如果你想預設就顯示所有圖書,即預設渲染
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。
DEMO
DefaultRoute
如果你不想預設顯示圖書或電影,而是另一個元件,比如歡迎資訊什麼的,可以使用
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),除非你點選「圖書」或「電影」。
DEMO
路由參數及嵌套路由
業務邏輯更複雜了,現在除了點選「圖書」顯示圖書清單,點選「電影」顯示電影清單外,點選某一本圖書(或某一部電影)還要顯示對應的詳情。
DEMO
首先更新路由對象
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,當你檢視某一本書的詳情時,書名及圖書菜單都處于高亮狀态,一條龍高亮。
DEMO
小技巧
這裡還有另外一個問題,如果我們想點選某本書的時候不再顯示圖書清單而是隻顯示菜單和圖書詳情該怎麼辦呢?我們再對路由對象進行小小的改動。
DEMO
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,不知道大家有沒有更好的辦法實作。
DEMO
ReactRouter小結
以上基本覆寫了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
版權聲明:本文為CSDN部落客「weixin_34411563」的原創文章,遵循CC 4.0 BY-SA版權協定,轉載請附上原文出處連結及本聲明。
原文連結:https://blog.csdn.net/weixin_34411563/article/details/92079081