中文 React Router

React/Router

文档已烧毁,封闭更新,详情请往 这里:

React Router 一个针对React而设想的路由处置惩罚方案、可以友爱的帮你处置惩罚React components 到URl之间的同步映照关联。

概览

在申明React Router可以帮你处置惩罚的题目之前我们来举一个没有援用React Router 的简朴例子。

没运用 React Router

var About = React.createClass({
  render: function () {
    return <h2>About</h2>;
  }
});

var Inbox = React.createClass({
  render: function () {
    return <h2>Inbox</h2>;
  }
});

var Home = React.createClass({
  render: function () {
    return <h2>Home</h2>;
  }
});

var App = React.createClass({
  render () {
    var Child;
    switch (this.props.route) {
      case 'about': Child = About; break;
      case 'inbox': Child = Inbox; break;
      default:      Child = Home;
    }

    return (
      <div>
        <h1>App</h1>
        <Child/>
      </div>
    )
  }
});

function render () {
  var route = window.location.hash.substr(1);
  React.render(<App route={route} />, document.body);
}

window.addEventListener('hashchange', render);
render(); // render initially

在hash值转变的时刻,App 将会依据this.props.route 值的转变来动态衬着 <Child/> component。
这模样的做法看起来很直接,然则这也会让全部运用程序变得越发庞杂。
我们可以想一想,假如组件 Inbox 有一些内嵌的子组件须要依据 比方 inbox/message/:id 或许 inbox/unread 等如许的路由划定规矩做动态衬着的时刻。我们须要一些越发智能的手腕来把路由信息通报给我们的App,如许Inbox 组件可以依据URL的映照关联来掌握哪些子组件应当须要被衬着。我们的许多组件应当依据URL的划定规矩来做动态衬着。在不运用路由划定规矩的前提下,庞杂一点的路由需求就须要我们写许多前提推断的代码去去处置惩罚实RL和层级组件的同步题目。

引入路由

处置惩罚庞杂的URL和层级组件之间的映照关联式React Router 的中心。我们运用声明式的体式格局为我们举的例子引入路由。我们运用JSX的体式格局来举行路由的设置,如许我们可以经由过程属性的体式格局来设置页面视图的层级关联。
先来看看路由的设置

var Router = require('react-router');
var Route = Router.Route;

// declare our routes and their hierarchy
var routes = (
  <Route handler={App}>
    <Route path="about" handler={About}/>
    <Route path="inbox" handler={Inbox}/>
  </Route>
);

我们删撤除一些在组件内推断路由逻辑的代码。然后用<RouteHandle/> 替代 <Child/>.然后代码变成下面这个模样。

var RouteHandler = Router.RouteHandler;

var App = React.createClass({
  render () {
    return (
      <div>
        <h1>App</h1>
        <RouteHandler/>
      </div>
    )
  }
});

末了我们须要监听url的变化来动态衬着运用,到场下面的代码。

  Router.run(routes, Router.HashLocation, (Root) => {
  React.render(<Root/>, document.body);
});

Root 是 React Router 路由婚配后决议衬着的最高层级的组件,通知 RouterHandle 应当衬着的内容是什么。
<Router/> 组件是不会被衬着的。只是一个建立内部路由划定规矩的设置对象。

接下来我们为运用增加更多的UI组件
如今我们设计给Inbox UI 增加Inbox message 子组件。起首我们须要增加一个新的Message组件。然后我们在原有的inbox路由下面为 Message 组件增加新的路由,如许就可以获得嵌套的UI。

var Message = React.createClass({
  render () {
    return <h3>Message</h3>;
  }
});

var routes = (
  <Route handler={App}>
    <Route path="about" handler={About}/>
    <Route path="inbox" handler={Inbox}>
      <Route path="messages/:id" handler={Message}/>
    </Route>
  </Route>
);

如今我们接见 inbox/message/jKei3c32c的URL就可以婚配到新的路由划定规矩并可以婚配到App->Inbox->Message 这个分支下的UI。

猎取url的参数
我们须要猎取到一些Url的信息,如许我们可以依据这些参数从服务器端猎取数据。我们把交给<Route/>婚配好的组件称为RouterHandler. RouterHandler 实例可以猎取到一些异常有效的属性当你衬着组件的时刻。特别是一些从URL动态猎取的参数信息。比如在我们举例中得 :id

var Message = React.createClass({
  componentDidMount: function () {
    // from the path `/inbox/messages/:id`
    var id = this.props.params.id;
    fetchMessage(id, function (err, message) {
      this.setState({ message: message });
    })
  },
  // ...
});

嵌套的UI和多层级的URLs是 不须要耦合的。
有了React Router,我们不须要用嵌套UI的体式格局来对应多层级的URL。反过来,猎取嵌套组件的UI,我们也不须要有多层级的URL与它对应。

比如说我们有/about/company 如许的URL,我们不须要嵌套UI组件到About组件中。

var routes = (
  <Route handler={App}>
    <Route path="about" handler={About}/>
    <Route path="about/company" handler={Company}/>
  </Route>
);

虽然说我们的URL是有层级嵌套的,然则我们UI组件中得 About 组件和 Company 组件却可以是相邻展平在同级目次的。

如今让我们往路由中增加url /archive/messages/:id 然后让该路由嵌套到inbox UI内里,纵然 这个URL不跟上层 Router 的URL 嵌套。我们须要做三件事让婚配下面划定规矩的路由一般事情。

1、url 要以 / 如许的绝对途径开首,这代表不会从父路由继续路由划定规矩。
2、嵌套在Inbox route 中的router 会致使UI组件的层级嵌套。
3、肯定你已经有必须的动态URL片断,在这里我们只要 :id ,所以处置惩罚起来相称简朴。

var routes = (
  <Route handler={App}>
    <Route path="inbox" handler={Inbox}>
      <Route path="messages/:id" handler={Message}/>
      <Route path="/archive/messages/:id" handler={Message}/>
    </Route>
  </Route>
);

这就是React Router的中心,运用的UI组件是层层嵌套的。如今我们可以让这些嵌套的UI组件和URL划定规矩坚持同步了。

Route 设置

DefaultRoute

一个RefaultRoute 是一个已婚配父组件会默许展现的子组件。
你希冀在没有子组件被婚配的时刻一个子RouterHandler老是可以衬着到页面。

Props
handle
RouterHandler 是你须要衬着到页面的婚配划定规矩的组件
name (可选)
当你运用linking 和 transitioning 的路由名字

举例

<Route path="/" handler={App}>

  <!--
    When the url is `/`, this route will be active. In other
    words, `Home` will be the `<RouteHandler/>` in `App`.
  -->
  <DefaultRoute handler={Home}/>

  <Route name="about" handler={About}/>
  <Route name="users" handler={Users}>
    <Route name="user" handler={User} path="/user/:id"/>

    <!-- when the url is `/users`, this will be active -->
    <DefaultRoute name="users-index" handler={UsersIndex}/>

  </Route>
</Route>

NotFoundRoute

NotFoundRoute 会在父组件婚配胜利但没有一个同级组件被婚配的时刻会被激活。
你可以运用它来处置惩罚不正当的链接。

提醒
NotFoundRoute不是针对当资本没有被找到而设想的。路由没有婚配到特定的URL和经由过程一个正当的URL没有查找到资本是有却别的。url course/123 是一个正当的url并可以婚配到对应的路由,所以它是找到了的意义。然则经由过程123 去婚配资本的时刻却没有找到,这个时刻我们并不像跳转到一个新的路由,我们可以设置差别的状况来选软差别的UI组件,而不是经由过程NotFoundRoute 来处置惩罚。

props

handler
RouterHandler 是你须要衬着到页面的婚配划定规矩的组件

举例

<Route path="/" handler={App}>
  <Route name="course" path="course/:courseId" handler={Course}>
    <Route name="course-dashboard" path="dashboard" handler={Dashboard}/>

    <!-- ie: `/course/123/foo` -->
    <NotFoundRoute handler={CourseRouteNotFound} />
  </Route>

  <!-- ie: `/flkjasdf` -->
  <NotFoundRoute handler={NotFound} />
</Route>

末了一个 NotFoundRoute 将会衬着到 APP 内。 第一个将会被衬着到Course 内。

Redirect

Recirect 可以跳转到别的一个路由中。

props

from
你想最先redirect的地点,包括一些动态的地点。默许为* ,如许任何婚配不到路由划定规矩的状况多回被重定向到别的一个处所。
to
你想要重定向到得路由名字。
params
默许状况下,这些参数将会自动通报到新的路由,你也可以指定他们,特别是你不须要的时刻。
query
params一样

举例

<!--
  lets say we want to change from `/profile/123` to `/about/123`
  and redirect `/get-in-touch` to `/contact`
-->
<Route handler={App}>
  <Route name="contact" handler={Contact}/>
  <Route name="about-user" path="about/:userId" handler={UserProfile}/>
  <Route name="course" path="course/:courseId">
    <Route name="course-dashboard" path="dashboard" handler={Dashboard}/>
    <Route name="course-assignments" path="assignments" handler={Assignments}/>
  </Route>

  <!-- `/get-in-touch` -> `/contact` -->
  <Redirect from="get-in-touch" to="contact" />

  <!-- `/profile/123` -> `/about/123` -->
  <Redirect from="profile/:userId" to="about-user" />

  <!-- `/profile/me` -> `/about-user/123` -->
  <Redirect from="profile/me" to="about-user" params={{userId: SESSION.USER_ID}} />
</Route>

<Redirect> 可以被安排到路由的任何层级。假如你挑选把它放在路由某一层级的下方,那末from途径也会婚配到它上层的途径。

Route

Route 用于声明式地映照路由划定规矩到你多层嵌套的运用组件。
props
name(可选)
name 在路由中是唯一的,被运用在 Link 组件和路由转换的要领中。
path(optional)
在url中运用的途径,假如不填写的话,途径就是name,假如name也没有的话,默许就是 /.
handler
当路由被婚配的时刻会被 RouteHander 衬着的组件。
children
路由是可以嵌套的,假如子路由的途径被婚配,那末父路由也处于激活状况。

ignoreScrollBehavior
当路由或许路由的params 转变的时刻,路由会依据scrollBehavior 来调解页面滚动条的位置。然则 你也可以不挑选这项功用,特别是在一些搜刮页面或许是 tab切换的页面。

Top-Level

Router.create

建立一个新的路由。

Signature
Router.create(options)

Options
routes

location

scrollBehavior

onAbort
Used server-side to know when a route was redirected.

Method
run(callback)
启动路由,和Router.run 一样

举例

// the more common API is
Router.run(routes, Router.HistoryLocation, callback);

// which is just a shortcut for
var router = Router.create({
  routes: routes,
  location: Router.HistoryLocation
});

router.run(callback);

Router.run

The main API into react router. It runs your routes, matching them against a location, and then calls back with the next state for you to render.

signature

Router.run(routes,[location,],callback)
参数
routes
location (可选)
默许值是Router.HashLocation 假如你设置了Location 那末它的转变会被监听。假如你设置了一个字符路劲,那末路由会马上婚配并实行回调函数。

举例

// Defaults to `Router.HashLocation`
// callback is called whenever the hash changes
Router.run(routes, callback);

// HTML5 History
// callback is called when history events happen
Router.run(routes, Router.HistoryLocation, callback);

// Server rendering
// callback is called once, immediately.
Router.run(routes, '/some/path', callback);

callback(Root,state)
回调函数吸收两个参数
1、 Root
2、 state

Root
是一个包括了一切婚配组件的一个组件,它用来衬着你的组件。
state
一个包括了婚配状况的对象。
state.path
带有查询参数的当前URL
state.action
一个触发路由转变的操纵
state.pathname
不带查询参数的URL
state.params
当前被激活路由婚配途径对应的参数 如 /:id 对应的id值.

state.query
当前被激活路由婚配途径对应的查询参数
state.routes
包括了婚配路由的数组,在组件衬着之前猎取数据会显得很有协助。
可以检察 example async-data

举例

基础用法

javascript
Router.run(routes, function (Root) {
// whenever the url changes, this callback is called again
React.render(<Root/>, document.body);
});

var resolveHash = require(‘when/keys’).all;

var SampleHandler = React.createClass({
statics: {

// this is going to be called in the `run` callback
fetchData: function (params) {
  return fetchStuff(params);
}

},
// …
});

Router.run(routes, Router.HistoryLocation, function (Root, state) {

// create the promises hash
var promises = state.routes.filter(function (route) {

// gather up the handlers that have a static `fetchData` method
return route.handler.fetchData;

}).reduce(function (promises, route) {

// reduce to a hash of `key:promise`
promises[route.name] = route.handler.fetchData(state.params);
return promises;

}, {});

resolveHash(promises).then(function (data) {

// wait until we have data to render, the old screen stays up until
// we render
React.render(<Root data={data}/>, document.body);

});
});

something.serve(function (req, res) {
Router.run(routes, req.path, function (Root, state) {

// could fetch data like in the previous example
fetchData(state.matches).then(function (data) {
  var html = React.renderToString(<Root data={data} />);
  res.send(html);
});

});
});


#Components

##Link
用于在运用程序中导航的一种重要体式格局。``Link``将会衬着出标签属性href 变得轻易被明白。
当``Link``定位的路由被激活的时刻自动 显现为 定义的 ``activeClassName`` 和/或许
``activeStyle`` 定义的款式。

**Props**
``to``
要被定位到的路由名字,或许是完全的途径

``params``

包括了名字/值的对象,和路由地点的动态段对应一致。

``query``

一个包括名字/值 的对象,它会成为地点中的查询参数

**举例**

// given a route config like this
<Route name=”user” path=”/users/:userId”/>

// create a link with this
<Link to=”user” params={{userId: “123”}}/>

// though, if your user properties match up to the dynamic segements:
<Link to=”user” params={user}/>


``query``

一个包装成javascript对象的字符串查询参数

``activeClassName``

当路由被激活是 ``Link`` 吸收的 className,默许值为 ``active``

``activeStyle ``

当路由被激活是链接元素 展现的style款式。

``onClick``

对点击时候的通例处置惩罚,仅仅在标签``<a>`` 上起效。挪用 ``e.preventDefault`` 或许是返回false 将会阻挠阻挠事宜发射。经由过程 ``e.stopPropagation()`` 将会阻挠时候冒泡。

**others**

你也可以在<a>上通报 props,比方 title,id , className 等。

**举例**

供应一个情势像 ``<Router name="user" path="/user/:userid" />:`` 如许的路由

<Link to=”user” params={{userId: user.id}} query={{foo: bar}}>{user.name}</Link>
<!– becomes one of these depending on your router and if the route is
active –>
Michael
Michael

<!– or if you have the full url already, you can just pass that in –>
<Link to=”/users/123?foo=bar”>{user.name}</Link>

<!– change the activeClassName –>
<Link activeClassName=”current” to=”user” params={{userId: user.id}}>{user.name}</Link>

<!– change style when link is active –>
<Link style={{color: ‘white’}} activeStyle={{color: ‘red’}} to=”user” params={{userId: user.id}} query={{foo: bar}}>{user.name}</Link>


##Root
React router 建立的运用顶层组件。

**举例**

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

**申明**
当前路由的实例和 ``Root`` 一致。

var MyRouter = Router.create({ routes });

MyRouter.run((Root) => {
Root === MyRouter; // true
});

当前这仅仅是一个完成的细节,我们会逐渐将它设想成一个大众的API。


##Route Handler
用户定义的一个组件,作为通报给``Routes`` 的一个 ``handler`` 属性。 路由会在你经由过程 ``RouterHandler`` 衬着组件的时刻给你注入一些属性值。同时在路由转换的时刻挪用一些生命周期的静态要领。

**注入的属性**

``params``

url 中的动态段。

``query``

url中的查询参数

``path``

完全的url 路劲

**举例**

// given a route like this:
<Route path=”/course/:courseId/students” handler={Students}/>

// and a url like this:
“/course/123/students?sort=name”

var Students = React.createClass({
render () {

this.props.params.courseId; // "123"
this.props.query.sort; // "name"
this.props.path; // "/course/123/students?sort=name"
// ...

}
});


**静态的生命周期要领**

你可以定义一些在路由转换时会挪用的静态要领到你的路由handler 对应的组件中。

``willTransitionTo(transition,params,query,callback)``

当一个handler 将要被衬着的时刻被挪用。为你供应了中缀或许是重定向的时机。你可以在异步挪用的时刻停息转换,在完成以后可以挪用``callback(error)``  要领。或许在参数列表中省略callback。

``willTranstionFrom(transition,component,callback)``

当一个被激活路由将要跳出的时刻给你供应了中缀跳出的要领。``component`` 是当前的组件。你能够须要检查一下 state 的状况来决议是不是须要跳出。

**关于 ``callback`` 的参数**

 假如你在参数列表中增加了callback,你须要在末了的时刻挪用它,纵然你运用的是重定向。

**举例**

var Settings = React.createClass({
statics: {

willTransitionTo: function (transition, params, query, callback) {
  auth.isLoggedIn((isLoggedIn) => {
    transition.abort();
    callback();
  });
},

willTransitionFrom: function (transition, component) {
  if (component.formHasUnsavedData()) {
    if (!confirm('You have unsaved information,'+
                 'are you sure you want to leave this page?')) {
      transition.abort();
    }
  }
}

}

//…
});

    原文作者:haiping
    原文地址: https://segmentfault.com/a/1190000002801128
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞