React Router 4.0 體驗

React Router 4.0 (如下簡稱 RR4) 已經正式發佈,它遵循React的設計理念,即萬物皆組件。因此 RR4 只是一堆 提供了導航功能的組件(還有若干對象和方法),具備聲明式(聲明式編程簡單來說就是你只須要關心作什麼,而無需關心如何去作,比如你寫 React 組件,只須要 render 出你想要的組件,至於組件是如何實現的是 React 要處理的事情。),可組合性的特色。、
RR4 本次採用單代碼倉庫模型架構(monorepo),這意味者這個倉庫裏面有若干相互獨立的包,分別是:
  • 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 靜態路由配置的小助手

引用

react-router 仍是 react-router-dom?

在 React 的使用中,咱們通常要引入兩個包, reactreact-dom,那麼 react-routerreact-router-dom 是否是兩個都要引用呢?
非也,坑就在這裏。他們兩個只要引用一個就好了,不一樣之處就是後者比前者多出了 <Link> <BrowserRouter> 這樣的 DOM 類組件。
所以咱們只需引用 react-router-dom 這個包就好了。固然,若是搭配 redux ,你還須要使用 react-router-redux
what is the diff between react-router-dom & react-router?

組件

<BrowserRouter>

一個使用了 HTML5 history API 的高階路由組件,保證你的 UI 界面和 URL 保持同步。此組件擁有如下屬性:javascript

basename: string
做用:爲全部位置添加一個基準URL
使用場景:假如你須要把頁面部署到服務器的二級目錄,你可使用 basename 設置到此目錄。java

<BrowserRouter basename="/minooo" />
<Link to="/react" /> // 最終渲染爲 <a href="/minooo/react">

  

getUserConfirmation: func
做用:導航到此頁面前執行的函數,默認使用 window.confirm
使用場景:當須要用戶進入頁面前執行什麼操做時可用,不過通常用到的很少。node

const getConfirmation = (message, callback) => {
  const allowTransition = window.confirm(message)
  callback(allowTransition)
}

 

<BrowserRouter getUserConfirmation={getConfirmation('Are you sure?', yourCallBack)} /> 

  

forceRefresh: bool
做用:當瀏覽器不支持 HTML5 的 history API 時強制刷新頁面。
使用場景:同上。react

const supportsHistory = 'pushState' in window.history
<BrowserRouter forceRefresh={!supportsHistory} />

keyLength: number
做用:設置它裏面路由的 location.key 的長度。默認是6。(key的做用:點擊同一個連接時,每次該路由下的 location.key都會改變,能夠經過 key 的變化來刷新頁面。)
使用場景:按需設置。git

<BrowserRouter keyLength={12} />

children: node
做用:渲染惟一子元素。
使用場景:做爲一個 Reac t組件,天生自帶 children 屬性。github

嘗試一下npm


<HashRouter>

Hash history 不支持 location.keylocation.state。另外因爲該技術只是用來支持舊版瀏覽器,所以更推薦你們使用 BrowserRouter,此API再也不做多餘介紹。編程


<Route>

<Route> 也許是 RR4 中最重要的組件了,重要到你必須理解它,學會它,用好它。它最基本的職責就是當頁面的訪問地址與 Route 上的 path 匹配時,就渲染出對應的 UI 界面。redux

<Route> 自帶三個 render method 和三個 props 。瀏覽器

render methods 分別是:

  • <Route component>
  • <Route render>
  • <Route children>
    每種 render method 都有不一樣的應用場景,同一個<Route> 應該只使用一種 render method ,大部分狀況下你將使用 component

props 分別是:

  • match
  • location
  • history
    全部的 render method 無一例外都將被傳入這些 props。

component
只有當訪問地址和路由匹配時,一個 React component 纔會被渲染,此時此組件接受 route props (match, location, history)。
當使用 component 時,router 將使用 React.createElement 根據給定的 component 建立一個新的 React 元素。這意味着若是你使用內聯函數(inline function)傳值給 component 將會產生沒必要要的重複裝載。對於內聯渲染(inline rendering), 建議使用 render prop。

<Route path="/user/:username" component={User} />
const User = ({ match }) => {
  return <h1>Hello {match.params.username}!</h1>
}

render: func
此方法適用於內聯渲染,並且不會產生上文說的重複裝載問題。

// 內聯渲染
<Route path="/home" render={() => <h1>Home</h1} />

// 包裝 組合
const FadingRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={props => (
    <FadeIn>
      <Component {...props} />
    </FaseIn>
  )} />
)

<FadingRoute path="/cool" component={Something} />

children: func
有時候你可能只想知道訪問地址是否被匹配,而後改變下別的東西,而不只僅是對應的頁面。

<ul>
  <ListItemLink to="/somewhere" />
  <ListItemLink to="/somewhere-ele" />
</ul>

const ListItemLink = ({ to, ...rest }) => (
  <Route path={to} children={({ match }) => (
    <li className={match ? 'active' : ''}>
      <Link to={to} {...rest} />
    </li>
  )}
)

path: string
任何能夠被 path-to-regexp解析的有效 URL 路徑

<Route path="/users/:id" component={User} />

若是不給path,那麼路由將老是匹配。

exact: bool
若是爲 true,path 爲 '/one' 的路由將不能匹配 '/one/two',反之,亦然。

strict: bool
對路徑末尾斜槓的匹配。若是爲 true。path 爲 '/one/' 將不能匹配 '/one' 但能夠匹配 '/one/two'。

若是要確保路由沒有末尾斜槓,那麼 strict 和
exact 都必須同時爲 true

嘗試一下


<Link>

爲你的應用提供聲明式,無障礙導航。

to: string
做用:跳轉到指定路徑
使用場景:若是隻是單純的跳轉就直接用字符串形式的路徑。

<Link to="/courses" />

  

to: object
做用:攜帶參數跳轉到指定路徑
做用場景:好比你點擊的這個連接將要跳轉的頁面須要展現此連接對應的內容,又好比這是個支付跳轉,須要把商品的價格等信息傳遞過去。

<Link to={{
  pathname: '/course',
  search: '?sort=name',
  state: { price: 18 }
}} />

replace: bool
爲 true 時,點擊連接後將使用新地址替換掉上一次訪問的地址,什麼意思呢,好比:你依次訪問 '/one' '/two' '/three' ’/four' 這四個地址,若是回退,將依次回退至 '/three' '/two' '/one' ,這符合咱們的預期,假如咱們把連接 '/three' 中的 replace 設爲 true 時。依次點擊 one two three four 而後再回退會發生什麼呢?會依次退至 '/three' '/one'! 爲此我作了個在線 demo,你們能夠調試體會一下 !

另外你能想到這個 prop 的用途是什麼呢?有人說在用 路由 作選項卡時候會用到。歡迎留言討論!

嘗試一下


<NavLink>

這是 <Link> 的特殊版,顧名思義這就是爲頁面導航準備的。由於導航須要有 「激活狀態」。

activeClassName: string
導航選中激活時候應用的樣式名,默認樣式名爲 active

<NavLink
  to="/about"
  activeClassName="selected"
>MyBlog</NavLink>

activeStyle: object
若是不想使用樣式名就直接寫style

<NavLink
  to="/about"
  activeStyle={{ color: 'green', fontWeight: 'bold' }}
>MyBlog</NavLink>

exact: bool
若爲 true,只有當訪問地址嚴格匹配時激活樣式纔會應用

strict: bool
若爲 true,只有當訪問地址後綴斜槓嚴格匹配(有或無)時激活樣式纔會應用

isActive: func
決定導航是否激活,或者在導航激活時候作點別的事情。無論怎樣,它不能決定對應頁面是否能夠渲染。

嘗試一下


<Switch>

只渲染出第一個與當前訪問地址匹配的 <Route><Redirect>

思考以下代碼,若是你訪問 /about,那麼組件 About User Nomatch 都將被渲染出來,由於他們對應的路由與訪問的地址 /about 匹配。這顯然不是咱們想要的,咱們只想渲染出第一個匹配的路由就能夠了,因而 <Switch> 應運而生!

<Route path="/about" component={About}/>
<Route path="/:user" component={User}/>
<Route component={NoMatch}/>

也許你會問,爲何 RR4 機制裏不默認匹配第一個符合要求的呢,答:這種設計容許咱們將多個 <Route> 組合到應用程序中,例如側邊欄(sidebars),麪包屑 等等。

另外,<Switch> 對於轉場動畫也很是適用,由於被渲染的路由和前一個被渲染的路由處於同一個節點位置!

<Fade>
  <Switch>
    {/* 用了Switch 這裏每次只匹配一個路由,全部只有一個節點。 */}
    <Route/>
    <Route/>
  </Switch>
</Fade>

<Fade>
  <Route/>
  <Route/>
  {/* 不用 Switch 這裏可能就會匹配多個路由了,即使匹配不到,也會返回一個null,使動畫計算增長了一些麻煩。 */}
</Fade> 

children: node
<Switch> 下的子節點只能是 <Route><Redirect> 元素。只有與當前訪問地址匹配的第一個子節點纔會被渲染。<Route> 元素用它們的 path 屬性匹配,<Redirect> 元素使用它們的 from 屬性匹配。若是沒有對應的 pathfrom,那麼它們將匹配任何當前訪問地址。

嘗試一下


<Redirect>

<Redirect> 渲染時將導航到一個新地址,這個新地址覆蓋在訪問歷史信息裏面的本該訪問的那個地址。

to: string
重定向的 URL 字符串

to: object
重定向的 location 對象

push: bool
若爲真,重定向操做將會把新地址加入到訪問歷史記錄裏面,而且沒法回退到前面的頁面。

from: string
須要匹配的將要被重定向路徑。

嘗試一下


Prompt

當用戶離開當前頁面前作出一些提示。

message: string
當用戶離開當前頁面時,設置的提示信息。

<Prompt message="肯定要離開?" />

message: func
當用戶離開當前頁面時,設置的回掉函數

<Prompt message={location => (
  `Are you sue you want to go to ${location.pathname}?` 
)} />

when: bool
經過設置必定條件要決定是否啓用 Prompt

嘗試一下


對象和方法

history

histoty 是 RR4 的兩大重要依賴之一(另外一個固然是 React 了),在不一樣的 javascript 環境中, history 以多種可以行駛實現了對會話(session)歷史的管理。

咱們會常用如下術語:

  • "browser history" - history 在 DOM 上的實現,用於支持 HTML5 history API 的瀏覽器
  • "hash history" - history 在 DOM 上的實現,用於舊版瀏覽器。
  • "memory history" - history 在內存上的實現,用於測試或非 DOM 環境(例如 React Native)。

history 對象一般具備如下屬性和方法:

  • length: number 瀏覽歷史堆棧中的條目數
  • action: string 路由跳轉到當前頁面執行的動做,分爲 PUSH, REPLACE, POP
  • location: object 當前訪問地址信息組成的對象,具備以下屬性:
  • pathname: string URL路徑
  • search: string URL中的查詢字符串
  • hash: string URL的 hash 片斷
  • state: string 例如執行 push(path, state) 操做時,location 的 state 將被提供到堆棧信息裏,state 只有在 browser 和 memory history 有效。
  • push(path, [state]) 在歷史堆棧信息里加入一個新條目。
  • replace(path, [state]) 在歷史堆棧信息裏替換掉當前的條目
  • go(n) 將 history 堆棧中的指針向前移動 n。
  • goBack() 等同於 go(-1)
  • goForward 等同於 go(1)
  • block(prompt) 阻止跳轉

history 對象是可變的,由於建議從 <Route> 的 prop 裏來獲取 location,而不是從 history.location 直接獲取。這樣能夠保證 React 在生命週期中的鉤子函數正常執行,例如如下代碼:

class Comp extends React.Component {
  componentWillReceiveProps(nextProps) {
    // locationChanged
    const locationChanged = nextProps.location !== this.props.location

    // 錯誤方式,locationChanged 永遠爲 false,由於history 是可變的
    const locationChanged = nextProps.history.location !== this.props.history.location
  }
}

location

location 是指你當前的位置,將要去的位置,或是以前所在的位置

{
  key: 'sdfad1'
  pathname: '/about',
  search: '?name=minooo'
  hash: '#sdfas',
  state: {
    price: 123
  }
}

在如下情境中能夠獲取 location 對象

  • Route component 中,以 this.props.location 獲取
  • Route render 中,以 ({location}) => () 方式獲取
  • Route children 中,以 ({location}) => () 方式獲取
  • withRouter 中,以 this.props.location 的方式獲取

location 對象不會發生改變,所以能夠在生命週期的回調函數中使用 location 對象來查看當前頁面的訪問地址是否發生改變。這種技巧在獲取遠程數據以及使用動畫時很是有用

componentWillReceiveProps(nextProps) {
  if (nextProps.location !== this.props.location) {
    // 已經跳轉了!
  }
}

能夠在不一樣情境中使用 location:

  • <Link to={location} />
  • <NaviveLink to={location} />
  • <Redirect to={location />
  • history.push(location)
  • history.replace(location)

match

match 對象包含了 <Route path> 如何與 URL 匹配的信息,具備如下屬性:

  • params: object 路徑參數,經過解析 URL 中的動態部分得到鍵值對
  • isExact: bool 爲 true 時,整個 URL 都須要匹配
  • path: string 用來匹配的路徑模式,用於建立嵌套的 <Route>
  • url: string URL 匹配的部分,用於嵌套的 <Link>

在如下情境中能夠獲取 match 對象

  • Route component 中,以 this.props.match獲取
  • Route render 中,以 ({match}) => () 方式獲取
  • Route children 中,以 ({match}) => () 方式獲取
  • withRouter 中,以 this.props.match的方式獲取
  • matchPath 的返回值

當一個 Route 沒有 path 時,它會匹配一切路徑。

相關文章
相關標籤/搜索