初探 React Router 4.0
React Router 4.0 (以下簡稱 RR4) 已經(jīng)正式發(fā)布,它遵循React的設(shè)計(jì)理念,即萬物皆組件。所以 RR4 只是一堆?提供了導(dǎo)航功能的組件(還有若干對(duì)象和方法),具有聲明式(引入即用),可組合性的特點(diǎn)。http://www.jianshu.com/p/e3adc9b5f75c
RR4 本次采用單代碼倉庫模型架構(gòu)(monorepo),這意味者這個(gè)倉庫里面有若干相互獨(dú)立的包,分別是:
- react-router?React Router 核心
- react-router-dom?用于 DOM 綁定的 React Router
- react-router-native?用于 React Native 的 React Router
- react-router-redux?React Router 和 Redux 的集成
- react-router-config?靜態(tài)路由配置的小助手
本文主要討論在 web app 中如何使用使用 RR4。
引用
react-router 還是 react-router-dom?
在 React 的使用中,我們一般要引入兩個(gè)包,react?和?react-dom,那么?react-router?和react-router-dom?是不是兩個(gè)都要引用呢?
非也,坑就在這里。他們兩個(gè)只要引用一個(gè)就行了,不同之處就是后者比前者多出了?<Link>?<BrowserRouter>?這樣的 DOM 類組件。
因此我們只需引用?react-router-dom?這個(gè)包就行了。當(dāng)然,如果搭配 redux ,你還需要使用?react-router-redux。
what is the diff between react-router-dom & react-router?
組件
<BrowserRouter>
一個(gè)使用了 HTML5 history API 的高階路由組件,保證你的 UI 界面和 URL 保持同步。此組件擁有以下屬性:
basename: string
作用:為所有位置添加一個(gè)基準(zhǔn)URL
使用場景:假如你需要把頁面部署到服務(wù)器的二級(jí)目錄,你可以使用?basename?設(shè)置到此目錄。
getUserConfirmation: func
作用:導(dǎo)航到此頁面前執(zhí)行的函數(shù),默認(rèn)使用 window.confirm
使用場景:當(dāng)需要用戶進(jìn)入頁面前執(zhí)行什么操作時(shí)可用,不過一般用到的不多。
forceRefresh: bool
作用:當(dāng)瀏覽器不支持 HTML5 的 history API 時(shí)強(qiáng)制刷新頁面。
使用場景:同上。
keyLength: number
作用:設(shè)置它里面路由的?location.key?的長度。默認(rèn)是6。(key的作用:點(diǎn)擊同一個(gè)鏈接時(shí),每次該路由下的?location.key都會(huì)改變,可以通過 key 的變化來刷新頁面。)
使用場景:按需設(shè)置。
children: node
作用:渲染唯一子元素。
使用場景:作為一個(gè) Reac t組件,天生自帶 children 屬性。
嘗試一下
<HashRouter>
Hash history 不支持?location.key?和?location.state。另外由于該技術(shù)只是用來支持舊版瀏覽器,因此更推薦大家使用 BrowserRouter,此API不再作多余介紹。
<Route>
<Route> 也許是 RR4 中最重要的組件了,重要到你必須理解它,學(xué)會(huì)它,用好它。它最基本的職責(zé)就是當(dāng)頁面的訪問地址與 Route 上的 path 匹配時(shí),就渲染出對(duì)應(yīng)的 UI 界面。
<Route> 自帶三個(gè) render method 和三個(gè) props 。
render methods 分別是:
- <Route component>
- <Route render>
- <Route children>
每種 render method 都有不同的應(yīng)用場景,同一個(gè)<Route>?應(yīng)該只使用一種 render method ,大部分情況下你將使用?component?。
props 分別是:
- match
- location
- history
所有的 render method 無一例外都將被傳入這些 props。
component
只有當(dāng)訪問地址和路由匹配時(shí),一個(gè) React component 才會(huì)被渲染,此時(shí)此組件接受 route props (match, location, history)。
當(dāng)使用?component?時(shí),router 將使用?React.createElement?根據(jù)給定的 component 創(chuàng)建一個(gè)新的 React 元素。這意味著如果你使用內(nèi)聯(lián)函數(shù)(inline function)傳值給?component將會(huì)產(chǎn)生不必要的重復(fù)裝載。對(duì)于內(nèi)聯(lián)渲染(inline rendering), 建議使用?renderprop。
render: func
此方法適用于內(nèi)聯(lián)渲染,而且不會(huì)產(chǎn)生上文說的重復(fù)裝載問題。
children: func
有時(shí)候你可能只想知道訪問地址是否被匹配,然后改變下別的東西,而不僅僅是對(duì)應(yīng)的頁面。
path: string
任何可以被?path-to-regexp解析的有效 URL 路徑
如果不給path,那么路由將總是匹配。
exact: bool
如果為 true,path 為 '/one' 的路由將不能匹配 '/one/two',反之,亦然。
strict: bool
對(duì)路徑末尾斜杠的匹配。如果為 true。path 為 '/one/' 將不能匹配 '/one' 但可以匹配 '/one/two'。
如果要確保路由沒有末尾斜杠,那么 strict 和
exact 都必須同時(shí)為 true
嘗試一下
<Link>
為你的應(yīng)用提供聲明式,無障礙導(dǎo)航。
to: string
作用:跳轉(zhuǎn)到指定路徑
使用場景:如果只是單純的跳轉(zhuǎn)就直接用字符串形式的路徑。
to: object
作用:攜帶參數(shù)跳轉(zhuǎn)到指定路徑
作用場景:比如你點(diǎn)擊的這個(gè)鏈接將要跳轉(zhuǎn)的頁面需要展示此鏈接對(duì)應(yīng)的內(nèi)容,又比如這是個(gè)支付跳轉(zhuǎn),需要把商品的價(jià)格等信息傳遞過去。
replace: bool
為 true 時(shí),點(diǎn)擊鏈接后將使用新地址替換掉上一次訪問的地址,什么意思呢,比如:你依次訪問 '/one' '/two' '/three' ’/four' 這四個(gè)地址,如果回退,將依次回退至 '/three' '/two' '/one' ,這符合我們的預(yù)期,假如我們把鏈接 '/three' 中的 replace 設(shè)為 true 時(shí)。依次點(diǎn)擊 one two three four 然后再回退會(huì)發(fā)生什么呢?會(huì)依次退至 '/three' '/one'! 為此我做了個(gè)在線 demo,大家可以調(diào)試體會(huì)一下 !
另外你能想到這個(gè) prop 的用途是什么呢?有人說在用 路由 做選項(xiàng)卡時(shí)候會(huì)用到。歡迎留言討論!
嘗試一下
<NavLink>
這是 <Link> 的特殊版,顧名思義這就是為頁面導(dǎo)航準(zhǔn)備的。因?yàn)閷?dǎo)航需要有 “激活狀態(tài)”。
activeClassName: string
導(dǎo)航選中激活時(shí)候應(yīng)用的樣式名,默認(rèn)樣式名為?active
activeStyle: object
如果不想使用樣式名就直接寫style
exact: bool
若為 true,只有當(dāng)訪問地址嚴(yán)格匹配時(shí)激活樣式才會(huì)應(yīng)用
strict: bool
若為 true,只有當(dāng)訪問地址后綴斜杠嚴(yán)格匹配(有或無)時(shí)激活樣式才會(huì)應(yīng)用
isActive: func
決定導(dǎo)航是否激活,或者在導(dǎo)航激活時(shí)候做點(diǎn)別的事情。不管怎樣,它不能決定對(duì)應(yīng)頁面是否可以渲染。
嘗試一下
<Switch>
只渲染出第一個(gè)與當(dāng)前訪問地址匹配的?<Route>?或?<Redirect>。
思考如下代碼,如果你訪問?/about,那么組件 About User Nomatch 都將被渲染出來,因?yàn)樗麄儗?duì)應(yīng)的路由與訪問的地址?/about?匹配。這顯然不是我們想要的,我們只想渲染出第一個(gè)匹配的路由就可以了,于是?<Switch>?應(yīng)運(yùn)而生!
<Route path="/about" component={About}/> <Route path="/:user" component={User}/> <Route component={NoMatch}/>也許你會(huì)問,為什么 RR4 機(jī)制里不默認(rèn)匹配第一個(gè)符合要求的呢,答:這種設(shè)計(jì)允許我們將多個(gè) <Route> 組合到應(yīng)用程序中,例如側(cè)邊欄(sidebars),面包屑 等等。
另外,<Switch>?對(duì)于轉(zhuǎn)場動(dòng)畫也非常適用,因?yàn)楸讳秩镜穆酚珊颓耙粋€(gè)被渲染的路由處于同一個(gè)節(jié)點(diǎn)位置!
<Fade><Switch>{/* 用了Switch 這里每次只匹配一個(gè)路由,所有只有一個(gè)節(jié)點(diǎn)。 */}<Route/><Route/></Switch> </Fade><Fade><Route/><Route/>{/* 不用 Switch 這里可能就會(huì)匹配多個(gè)路由了,即便匹配不到,也會(huì)返回一個(gè)null,使動(dòng)畫計(jì)算增加了一些麻煩。 */} </Fade>children: node
<Switch>?下的子節(jié)點(diǎn)只能是?<Route>?或?<Redirect>?元素。只有與當(dāng)前訪問地址匹配的第一個(gè)子節(jié)點(diǎn)才會(huì)被渲染。<Route>?元素用它們的?path?屬性匹配,<Redirect>?元素使用它們的?from?屬性匹配。如果沒有對(duì)應(yīng)的?path?或?from,那么它們將匹配任何當(dāng)前訪問地址。
嘗試一下
<Redirect>
<Redirect>?渲染時(shí)將導(dǎo)航到一個(gè)新地址,這個(gè)新地址覆蓋在訪問歷史信息里面的本該訪問的那個(gè)地址。
to: string
重定向的 URL 字符串
to: object
重定向的 location 對(duì)象
push: bool
若為真,重定向操作將會(huì)把新地址加入到訪問歷史記錄里面,并且無法回退到前面的頁面。
from: string
需要匹配的將要被重定向路徑。
嘗試一下
Prompt
當(dāng)用戶離開當(dāng)前頁面前做出一些提示。
message: string
當(dāng)用戶離開當(dāng)前頁面時(shí),設(shè)置的提示信息。
message: func
當(dāng)用戶離開當(dāng)前頁面時(shí),設(shè)置的回掉函數(shù)
when: bool
通過設(shè)置一定條件要決定是否啟用 Prompt
嘗試一下
對(duì)象和方法
history
histoty 是 RR4 的兩大重要依賴之一(另一個(gè)當(dāng)然是 React 了),在不同的 javascript 環(huán)境中, history 以多種能夠行駛實(shí)現(xiàn)了對(duì)會(huì)話(session)歷史的管理。
我們會(huì)經(jīng)常使用以下術(shù)語:
- "browser history" - history 在 DOM 上的實(shí)現(xiàn),用于支持 HTML5 history API 的瀏覽器
- "hash history" - history 在 DOM 上的實(shí)現(xiàn),用于舊版瀏覽器。
- "memory history" - history 在內(nèi)存上的實(shí)現(xiàn),用于測試或非 DOM 環(huán)境(例如 React Native)。
history 對(duì)象通常具有以下屬性和方法:
- length: number 瀏覽歷史堆棧中的條目數(shù)
- action: string 路由跳轉(zhuǎn)到當(dāng)前頁面執(zhí)行的動(dòng)作,分為 PUSH, REPLACE, POP
- location: object 當(dāng)前訪問地址信息組成的對(duì)象,具有如下屬性:
- pathname: string URL路徑
- search: string URL中的查詢字符串
- hash: string URL的 hash 片段
- state: string 例如執(zhí)行 push(path, state) 操作時(shí),location 的 state 將被提供到堆棧信息里,state 只有在 browser 和 memory history 有效。
- push(path, [state]) 在歷史堆棧信息里加入一個(gè)新條目。
- replace(path, [state]) 在歷史堆棧信息里替換掉當(dāng)前的條目
- go(n) 將 history 堆棧中的指針向前移動(dòng) n。
- goBack() 等同于 go(-1)
- goForward 等同于 go(1)
- block(prompt) 阻止跳轉(zhuǎn)
history 對(duì)象是可變的,因?yàn)榻ㄗh從?<Route>?的 prop 里來獲取 location,而不是從 history.location 直接獲取。這樣可以保證 React 在生命周期中的鉤子函數(shù)正常執(zhí)行,例如以下代碼:
class Comp extends React.Component {componentWillReceiveProps(nextProps) {// locationChangedconst locationChanged = nextProps.location !== this.props.location// 錯(cuò)誤方式,locationChanged 永遠(yuǎn)為 false,因?yàn)閔istory 是可變的const locationChanged = nextProps.history.location !== this.props.history.location} }location
location 是指你當(dāng)前的位置,將要去的位置,或是之前所在的位置
{key: 'sdfad1'pathname: '/about',search: '?name=minooo'hash: '#sdfas',state: {price: 123} }在以下情境中可以獲取 location 對(duì)象
- 在?Route component?中,以 this.props.location 獲取
- 在?Route render?中,以 ({location}) => () 方式獲取
- 在?Route children?中,以 ({location}) => () 方式獲取
- 在?withRouter?中,以 this.props.location 的方式獲取
location 對(duì)象不會(huì)發(fā)生改變,因此可以在生命周期的回調(diào)函數(shù)中使用 location 對(duì)象來查看當(dāng)前頁面的訪問地址是否發(fā)生改變。這種技巧在獲取遠(yuǎn)程數(shù)據(jù)以及使用動(dòng)畫時(shí)非常有用
componentWillReceiveProps(nextProps) {if (nextProps.location !== this.props.location) {// 已經(jīng)跳轉(zhuǎn)了!} }可以在不同情境中使用 location:
- <Link to={location} />
- <NaviveLink to={location} />
- <Redirect to={location />
- history.push(location)
- history.replace(location)
match
match 對(duì)象包含了 <Route path> 如何與 URL 匹配的信息,具有以下屬性:
- params: object 路徑參數(shù),通過解析 URL 中的動(dòng)態(tài)部分獲得鍵值對(duì)
- isExact: bool 為 true 時(shí),整個(gè) URL 都需要匹配
- path: string 用來匹配的路徑模式,用于創(chuàng)建嵌套的 <Route>
- url: string URL 匹配的部分,用于嵌套的 <Link>
在以下情境中可以獲取 match 對(duì)象
- 在?Route component?中,以 this.props.match獲取
- 在?Route render?中,以 ({match}) => () 方式獲取
- 在?Route children?中,以 ({match}) => () 方式獲取
- 在?withRouter?中,以 this.props.match的方式獲取
- matchPath 的返回值
當(dāng)一個(gè) Route 沒有 path 時(shí),它會(huì)匹配一切路徑。
總結(jié)
以上是生活随笔為你收集整理的初探 React Router 4.0的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从 npm 迁移至yarn
- 下一篇: CSS Modules 用法教程