react-router使用總結

react-router APIjavascript

基本用法

安裝命令:html

$ npm install -S react-router

使用展現:java

import { Router } from 'react-router';
render(<Router/>, document.getElementById('app'));

Router組件自己只是一個容器,真正的路由要經過Route組件定義。react

import { Router, Route, hashHistory } from 'react-router';

render((
  <Router history={hashHistory}>
    <Route path="/" component={App}/>
  </Router>
), document.getElementById('app'));

代碼解釋:git

  • 用戶訪問根路由/(好比http://www.example.com/),組件APP就會加載到document.getElementById('app')。github

  • Router組件有一個參數history,它的值hashHistory表示,路由的切換由URL的hash變化決定,即URL的#部分發生變化。舉例來講,用戶訪問http://www.example.com/,實際會看到的是http://www.example.com/#/npm

嵌套路由

Route組件定義了URL路徑與組件的對應關係。你能夠同時使用多個Route組件。瀏覽器

<Router history={hashHistory}>
  <Route path="/" component={App}/>
  <Route path="/repos" component={Repos}/>
  <Route path="/about" component={About}/>
</Router>

上面代碼中,用戶訪問/repos時,會先加載App組件,而後在它的內部再加載Repos組件。服務器

<App>
  <Repos/>
</App>

App組件要寫成下面的樣子。react-router

export default React.createClass({
  render() {
    return <div>
      {this.props.children}
    </div>
  }
})

上面代碼中,App組件的this.props.children屬性就是子組件。

子路由也能夠不寫在Router組件裏面,單獨傳入Router組件的routes屬性。

let routes = <Route path="/" component={App}>
  <Route path="/repos" component={Repos}/>
  <Route path="/about" component={About}/>
</Route>;

<Router routes={routes} history={browserHistory}/>

path屬性

Route組件的path屬性指定路由的匹配規則。這個屬性是能夠省略的,這樣的話,無論路徑是否匹配,老是會加載指定組件。

<Route path="inbox" component={Inbox}>
   <Route path="messages/:id" component={Message} />
</Route>

上面代碼中,當用戶訪問/inbox/messages/:id時,會加載下面的組件。

若是省略外層Routepath參數,寫成下面的樣子。

<Route component={Inbox}>
  <Route path="inbox/messages/:id" component={Message} />
</Route>

通配符

<Route path="/hello/:name">
// 匹配 /hello/michael
// 匹配 /hello/ryan
<Route path="/hello(/:name)">
// 匹配 /hello
// 匹配 /hello/michael
// 匹配 /hello/ryan
<Route path="/files/*.*">
// 匹配 /files/hello.jpg
// 匹配 /files/hello.html
<Route path="/files/*">
// 匹配 /files/ 
// 匹配 /files/a
// 匹配 /files/a/b

通配符規則:

  • :paramName匹配URL的一個部分,直到遇到下一個/、?、#爲止。這個路徑參數能夠經過this.props.params.paramName取出。

  • ()表示URL的這個部分是可選的。

  • *匹配任意字符,直到模式裏面的下一個字符爲止。匹配方式是非貪婪模式。

  • **匹配任意字符,直到下一個/、?、#爲止。匹配方式是貪婪模式。

經常使用組件

IndexRoute

上面的代碼會發現訪問根路徑會加載不到子組件。IndexRoute就是解決這個問題,顯式指定Home是根路由的子組件,即指定默認狀況下加載的子組件。你能夠把IndexRoute想象成某個路徑的index.html。

<Router>
  <Route path="/" component={App}>
    <IndexRoute component={Home}/>
    <Route path="accounts" component={Accounts}/>
    <Route path="statements" component={Statements}/>
  </Route>
</Router>

IndexRoute組件沒有路徑參數path

Redirect

<Redirect>組件用於路由的跳轉,即用戶訪問一個路由,會自動跳轉到另外一個路由。

<Route path="inbox" component={Inbox}>
  {/* 從 /inbox/messages/:id 跳轉到 /messages/:id */}
  <Redirect from="messages/:id" to="/messages/:id" />
</Route>

IndexRedirect

IndexRedirect組件用於訪問根路由的時候,將用戶重定向到某個子組件。

<Route path="/" component={App}>
  <IndexRedirect to="/welcome" />
  <Route path="welcome" component={Welcome} />
  <Route path="about" component={About} />
</Route>

RouterContext

  • push(pathOrLoc)

    router.push('/users/12')
    
    // or with a location descriptor object
    router.push({
     pathname: '/users/12',
     query: { modal: true },
     state: { fromDashboard: true }
    })
  • replace(pathOrLoc)

  • go(n)

  • goBack()

  • goForward()

  • setRouteLeaveHook(route, hook)

Link

Link組件用於取代<a>元素,生成一個連接,容許用戶點擊後跳轉到另外一個路由。它基本上就是<a>元素的React 版本,能夠接收Router的狀態。

render() {
  return <div>
    <ul role="nav">
      <li><Link to="/about">About</Link></li>
      <li><Link to="/repos">Repos</Link></li>
    </ul>
  </div>
}

若是但願當前的路由與其餘路由有不一樣樣式,這時可使用Link組件的activeStyle屬性

<Link to="/about" activeStyle={{color: 'red'}}>About</Link>
<Link to="/repos" activeStyle={{color: 'red'}}>Repos</Link>

另外一種作法是,使用activeClassName指定當前路由的Class

<Link to="/about" activeClassName="active">About</Link>
<Link to="/repos" activeClassName="active">Repos</Link>

IndexLink

若是連接到根路由/,不要使用Link組件,而要使用IndexLink組件。

這是由於對於根路由來講,activeStyleactiveClassName會失效,或者說老是生效,由於/會匹配任何子路由。而IndexLink組件會使用路徑的精確匹配。

<IndexLink to="/" activeClassName="active">
  Home
</IndexLink>

另外一種方法是使用Link組件的onlyActiveOnIndex屬性,也能達到一樣效果。

<Link to="/" activeClassName="active" onlyActiveOnIndex={true}>
  Home
</Link>

實際上,IndexLink就是對Link組件的onlyActiveOnIndex屬性的包裝。

history

Router組件的history屬性,用來監聽瀏覽器地址欄的變化,並將URL解析成一個地址對象,供 React Router 匹配。

  • hashHistory

    • 若是設爲hashHistory,路由將經過URL的hash部分(#)切換,URL的形式相似example.com/#/some/path。

  • browserHistory

    • 若是設爲browserHistory,瀏覽器的路由就再也不經過Hash完成了,而顯示正常的路徑example.com/some/path,背後調用的是瀏覽器的History API

    • 種狀況須要對服務器改造。不然用戶直接向服務器請求某個子路由,會顯示網頁找不到的404錯誤。

  • createMemoryHistory

    • createMemoryHistory主要用於服務器渲染。它建立一個內存中的history對象,不與瀏覽器URL互動。

    const history = createMemoryHistory(location)
  • useRouterHistory(createHistory)

import createHashHistory from 'history/lib/createHashHistory'
const history = useRouterHistory(createHashHistory)({ queryKey: false })

表單處理

Link組件用於正常的用戶點擊跳轉,可是有時還須要表單跳轉、點擊按鈕跳轉等操做。這些狀況怎麼跟React Router對接呢?

<form onSubmit={this.handleSubmit}>
  <input type="text" placeholder="userName"/>
  <input type="text" placeholder="repo"/>
  <button type="submit">Go</button>
</form>

第一種方法是使用browserHistory.push

import { browserHistory } from 'react-router'

// ...
  handleSubmit(event) {
    event.preventDefault()
    const userName = event.target.elements[0].value
    const repo = event.target.elements[1].value
    const path = `/repos/${userName}/${repo}`
    browserHistory.push(path)
  }

第二種方法是使用context對象。

export default React.createClass({

  // ask for `router` from context
  contextTypes: {
    router: React.PropTypes.object
  },

  handleSubmit(event) {
    // ...
    this.context.router.push(path)
  },
})

常見配置方案

React.render((
  <Router>
    <Route path="/" component={App}>
      <Route path="about" component={About} />
      <Route path="inbox" component={Inbox}>
        <Route path="messages/:id" component={Message} />
      </Route>
    </Route>
  </Router>
), document.body)

| URL | 組件|
| ------| ------ |
| / | APP |
| /about | App -> About |
| /inbox | App -> Inbox |
| /inbox/messages/:id | App -> Inbox -> Message |

添加首頁

React.render((
  <Router>
    <Route path="/" component={App}>
      {/* 當 url 爲/時渲染 Dashboard */}
      <IndexRoute component={Dashboard} />
      <Route path="about" component={About} />
      <Route path="inbox" component={Inbox}>
        <Route path="messages/:id" component={Message} />
      </Route>
    </Route>
  </Router>
), document.body)
URL 組件
/ App -> Dashboard
/about App -> About
/inbox App -> Inbox
/inbox/messages/:id App -> Inbox -> Message

讓 UI 從 URL 中解耦出來

React.render((
  <Router>
    <Route path="/" component={App}>
      <IndexRoute component={Dashboard} />
      <Route path="about" component={About} />
      <Route path="inbox" component={Inbox}>
        {/* 使用 /messages/:id 替換 messages/:id */}
        <Route path="/messages/:id" component={Message} />
      </Route>
    </Route>
  </Router>
), document.body)
URL 組件
/ App -> Dashboard
/about App -> About
/inbox App -> Inbox
/messages/:id App -> Inbox -> Message

兼容舊的 URL

如今任何人訪問 /inbox/messages/5 都會看到一個錯誤頁面。

import { Redirect } from 'react-router'

React.render((
  <Router>
    <Route path="/" component={App}>
      <IndexRoute component={Dashboard} />
      <Route path="about" component={About} />
      <Route path="inbox" component={Inbox}>
        <Route path="/messages/:id" component={Message} />

        {/* 跳轉 /inbox/messages/:id 到 /messages/:id */}
        <Redirect from="messages/:id" to="/messages/:id" />
      </Route>
    </Route>
  </Router>
), document.body)

替換的配置方式

const routeConfig = [
  { path: '/',
    component: App,
    indexRoute: { component: Dashboard },
    childRoutes: [
      { path: 'about', component: About },
      { path: 'inbox',
        component: Inbox,
        childRoutes: [
          { path: '/messages/:id', component: Message },
          { path: 'messages/:id',
            onEnter: function (nextState, replaceState) {
              replaceState(null, '/messages/' + nextState.params.id)
            }
          }
        ]
      }
    ]
  }
]

React.render(<Router routes={routeConfig} />, document.body)

轉載自react router使用教程

相關文章
相關標籤/搜索