React-Router學習整理


歡迎大家指導與討論 : )

  一、前言

    本文摘要:react-router的基本用法動畫效果與路由,路由權限控制,路由離開確認,根據路由切分的按需加載,路由組件的屬性。本文是筆者在學習時整理的筆記,由於技術水平還不夠高,有錯誤的地方懇請各位指出,共同進步O(∩_∩)O

  二、基本用法

    二、1 路由定義(摘要: Router, Route)

      在一個路由系統中,我們需要定義好路由表。我們需要用Router組件包含我們的路由表,通過Route來聲明單個的路由。同時,每個路由應該與它所屬的組件一一對應

render(( <Router >//開始創建路由表
    <Route path="/" component={App}>//聲明每一個路由
      <Route path="/about" component={About}/>
      <Route path="users" component={Users}>//每個路由
        <Route path=":id" component={User}/>//對應一個Component
      </Route>
    </Route>
  </Router>
), document.getElementById('example'))

//其他定義路由表的方法

import routes from './config/routes'

render(<Router history={browserHistory} routes={routes}/>, document.getElementById('example'))

    二、2 路由嵌套(摘要: IndexRouter, this.props.children)

      如何實現路由的嵌套呢,與Angular路由一樣,路由的嵌套需要兩個條件。一、在創建路由表的時候就聲明好嵌套的規則(ng中的$stateProvider);二、需要有一個view來安放所要嵌套的子頁面(ng中的ui-view)。其中,我們還可以在嵌套層的首個路由聲明中,使用IndexRoute來聲明該路由下的默認路由(類似於ng中$urlProvider.otherwise)

//有嵌套與默認頁面的路由表
render(( <Router >
    <Route path="/" component={App}>
      <IndexRoute component={Index}/>//設置默認頁面
      <Route path="/about" component={About}/>
      <Route path="users" component={Users}>
        <IndexRoute component={UsersIndex}/>//設置默認頁面
        <Route path=":id" component={User}/>
      </Route>
    </Route>
  </Router>
), document.getElementById('example')) //一個用於安放子頁(子路由)的view
class Users extends React.Component { render() { return ( <div>
        <h2>Users</h2>
        {this.props.children}//此處相當於<ui-view>
      </div>
 ) } }

    二、3 路由跳轉(摘要: Link,to)

      我們需要一個Link組件幫助我們實現路由的的跳轉  <li><Link to="/users" >/users</Link></li> ,最終Link組件會被渲染為<a>標簽。to屬性是我們所要跳轉的路由pathname(類似於ng中的ui-sref / href)

      二、3 . 1 父子路由的參數穿透傳遞(摘要: to = {`/xx/${xxx}/`} )

        若父路由中包含不確定參數,而我們又想把該參數往下級傳遞,這時候我們需要這樣子做

//路由配置
      <Route path="user/:userID" component={User}>
        <Route path="tasks/:taskID" component={Task} />
        <Redirect from="todos/:taskID" to="tasks/:taskID" />
      </Route>
//子級路由
<li><Link to={`/user/${userID}/tasks/foo`} activeClassName="active">foo task</Link></li>

      二、3 . 2 帶參數的路由跳轉

<li><Link      to={{ pathname: '/users/ryan', query: { foo: 'bar' } }} activeStyle={ACTIVE}>/users/ryan?foo=bar</Link></li>

      二、3 . 3 函數內跳轉(摘要: this.context.router.push('/'))

          this.context.router.push('/') ,注:這個寫法會把跳轉載入瀏覽器歷史,若不想留下歷史記錄則可以 this.context.router.replace('/') 

  三、帶有動畫效果的路由切換(摘要: ReactCSSTransitionGroup)

    當我們需要在路由切換時帶有一定的動畫效果時,我們便需要 react-addons-css-transition-group 這個插件了。使用ReactCSSTransitionGroup組件來包含我們需要呈現動畫效果的view

class App extends Component { render() { return ( <div>
        <ul>
          <li><Link to="/page1">Page 1</Link></li>
          <li><Link to="/page2">Page 2</Link></li>
        </ul>

        <ReactCSSTransitionGroup component="div"  transitionName="example"  transitionEnterTimeout={500}  transitionLeaveTimeout={500} > {React.cloneElement(this.props.children, { key: this.props.location.pathname })} </ReactCSSTransitionGroup>
           //克隆所有子節點,單獨的{this.props.children}沒有動畫效果
      </div>
 ) } }

  四、路由的權限控制(摘要: onEnter、context.router)

    單頁應用路由的權限控制的基本思路是:監聽路由的改變,每當路由將要發生改變,我們就使用一個中間服務(該服務介於上一級路由和將要到達路由之間啟動),來判斷我們是否有進入這個路由的權限,有的話直接進入,沒有的話就redirect。在React中,為某個路由進行權限監聽的方式是onEnter <Route path="page" component={Page} onEnter={requireCredentials}/> ,該onEnter屬性對應連着一個具有判斷權限的中間服務。我們通過上一級路由來啟動這個服務。假設我們需要從'/form'到'/page'之間做一個判斷,在'/form'中填寫特定字段后才能成功跳轉,否則redirect到'/error'

//form
const Form = createClass({ //省略部分代碼
 submitAction(event) { event.preventDefault(); //通過context傳輸數據
    //通過url的query字段傳輸數據
    //也可以通過制定其他服務來傳輸數據
    this.context.router.push({ pathname: '/page', query: { qsparam: this.state.value } }) }, render() { return ( <form onSubmit={this.submitAction}>
        //省略部分代碼
        <button type="submit">Submit </button>
      </form>
 ) } }) //路由權限控制
<Route path="page" component={Page} onEnter={requireCredentials}/>

//權限控制的中間服務
function requireCredentials(nextState, replace, next) { //獲取傳輸過來的數據
  if (query.qsparam) { serverAuth(query.qsparam) .then( () => next(),//成功,通過next()成功跳轉
      () => { replace('/error')//重定向
 next() } ) } else { replace('/error') next() } }  

     其中,onEnter所指向的函數是 type EnterHook = (nextState: RouterState, replace: RedirectFunction, callback?: Function) => any; 其中,nextState作為第一個參數,其所帶的信息有如下:

type RouterState = { location: Location; routes: Array<Route>; params: Params; components: Array<Component>; };

       其中,replace函數一旦被使用到,則在函數內部跳轉到一個新url,返回時也要帶上必要的信息,如下

type RedirectFunction = (state: ?LocationState, pathname: Pathname | Path, query: ?Query) => void;

   六、路由離開確認(摘要: componentWillMount, this.context.router.setRouteLeaveHook) 

     若我們需要在路由切換,在離開當前頁面的時候做一些確認工作,我們可以通過setRouteLeaveHook函數,為離開前執行一些操作

//Component內部
 componentWillMount() { this.context.router.setRouteLeaveHook( this.props.route, this.routerWillLeave ) } routerWillLeave() { if (xxx) //...
  },

  七、根據路由按需加載組件

    按需加載在單頁應用中的好處不言而喻,按業務模塊切分代碼能使首次加載資源所需要的時間大大降低,能在一定程度上增強用戶體驗。但首先我們需要整理一下我們的項目結構(此demo是按路由切分的,另外還能按業務模塊進行切分)

    七 . 1 項目結構

    七 . 2 路由表配置(app.js)

    七 . 3 對應組件的加載配置(routes/hello/index.js和routes/test/index.js)

 

  八、路由組件的屬性(摘要: this.props)

  九、路由Location屬性

type Location = { pathname: Pathname; search: QueryString; query: Query; state: LocationState; action: Action; key: LocationKey; };

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM