资讯专栏INFORMATION COLUMN

中文 React Router

刘德刚 / 594人阅读

摘要:是你需要渲染到页面的匹配规则的组件举例最后一个将会渲染到内。举例回调函数接收两个参数是一个包含了所有匹配组件的一个组件,它用来渲染你的组件。调用或者是返回将会阻止阻止事件发射。

React/Router 文档已废弃,关闭更新,详情请往 这里:

React Router 一个针对React而设计的路由解决方案、可以友好的帮你解决React components 到URl之间的同步映射关系。

概览

在阐明React Router可以帮你解决的问题之前我们来举一个没有引用React Router 的简单例子。

没使用 React Router

var About = React.createClass({
  render: function () {
    return 

About

; } }); var Inbox = React.createClass({ render: function () { return

Inbox

; } }); var Home = React.createClass({ render: function () { return

Home

; } }); 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 (

App

) } }); function render () { var route = window.location.hash.substr(1); React.render(, document.body); } window.addEventListener("hashchange", render); render(); // render initially

在hash值改变的时候,App 将会根据this.props.route 值的改变来动态渲染 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 = (
  
    
    
  
);

我们删除掉一些在组件内判断路由逻辑的代码。然后用 替换 .然后代码变成下面这个样子。

var RouteHandler = Router.RouteHandler;

var App = React.createClass({
  render () {
    return (
      

App

) } });

最后我们需要监听url的变化来动态渲染应用,加入下面的代码。

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

Root 是 React Router 路由匹配后决定渲染的最高层级的组件,告诉 RouterHandle 应该渲染的内容是什么。
组件是不会被渲染的。只是一个创建内部路由规则的配置对象。

接下来我们为应用添加更多的UI组件
现在我们计划给Inbox UI 添加Inbox message 子组件。首先我们需要添加一个新的Message组件。然后我们在原有的inbox路由下面为 Message 组件添加新的路由,这样就可以得到嵌套的UI。

var Message = React.createClass({
  render () {
    return 

Message

; } }); var routes = ( );

现在我们访问 inbox/message/jKei3c32c的URL就可以匹配到新的路由规则并可以匹配到App->Inbox->Message 这个分支下的UI。

获取url的参数
我们需要获取到一些Url的信息,这样我们可以根据这些参数从服务器端获取数据。我们把交给匹配好的组件称为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 = (
  
    
    
  
);

虽然说我们的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 = (
  
    
      
      
    
  
);

这就是React Router的核心,应用的UI组件是层层嵌套的。现在我们可以让这些嵌套的UI组件和URL规则保持同步了。

Route 配置 DefaultRoute

一个RefaultRoute 是一个已匹配父组件会默认展示的子组件。
你期望在没有子组件被匹配的时候一个子RouterHandler总是能够渲染到页面。

Props
handle
RouterHandler 是你需要渲染到页面的匹配规则的组件
name (可选)
当你使用linking 和 transitioning 的路由名字

举例



  
  

  
  
    

    
    

  
NotFoundRoute

NotFoundRoute 会在父组件匹配成功但没有一个同级组件被匹配的时候会被激活。
你可以使用它来处理不合法的链接。

提示
NotFoundRoute不是针对当资源没有被找到而设计的。路由没有匹配到特定的URL和通过一个合法的URL没有查找到资源是有却别的。url course/123 是一个合法的url并能够匹配到对应的路由,所以它是找到了的意思。但是通过123 去匹配资源的时候却没有找到,这个时候我们并不像跳转到一个新的路由,我们可以设置不同的状态来选软不同的UI组件,而不是通过NotFoundRoute 来解决。

props

handler
RouterHandler 是你需要渲染到页面的匹配规则的组件

举例


  
    

    
    
  

  
  

最后一个 NotFoundRoute 将会渲染到 APP 内。 第一个将会被渲染到Course 内。

Redirect

Recirect 可以跳转到另外一个路由中。

props

from
你想开始redirect的地址,包括一些动态的地址。默认为* ,这样任何匹配不到路由规则的情况多回被重定向到另外一个地方。
to
你想要重定向到得路由名字。
params
默认情况下,这些参数将会自动传递到新的路由,你也可以指定他们,特别是你不需要的时候。
query
params一样

举例



  
  
  
    
    
  

  
  

  
  

  
  

能够被放置到路由的任何层级。如果你选择把它放在路由某一层级的下方,那么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(, 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(, 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();
  res.send(html);
});

});
});

#Components

##Link
用于在应用程序中导航的一种主要方式。``Link``将会渲染出标签属性href 变得容易被理解。
当``Link``定位的路由被激活的时候自动 显示为 定义的 ``activeClassName`` 和/或者
``activeStyle`` 定义的样式。

**Props**
``to``
要被定位到的路由名字,或者是完整的路径

``params``

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

``query``

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

**举例**

// given a route config like this

// create a link with this

// though, if your user properties match up to the dynamic segements:

``query``

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

``activeClassName``

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

``activeStyle ``

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

``onClick``

对点击时间的常规处理,仅仅在标签```` 上起效。调用 ``e.preventDefault`` 或者是返回false 将会阻止阻止事件发射。通过 ``e.stopPropagation()`` 将会阻止时间冒泡。

**others**

你也可以在上传递 props,例如 title,id , className 等。

**举例**

提供一个形式像 ``:`` 这样的路由

{user.name}

Michael
Michael


{user.name}


{user.name}


{user.name}

##Root
React router 创建的应用顶层组件。

**举例**

Router.run(routes, (Root) => {
React.render(, 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:

// 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();
    }
  }
}

}

//...
});

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/92332.html

相关文章

  • 前端综合性文档和教程总结(持续更新)

    摘要:小弟在前端摸爬滚打一段时间,发现前端的比较好的文档比较分散,特别是中文的,我平时都是收藏在浏览器里,以后有好的教程和综合性的文档我会更新到这里。小组中文文档,很全。 小弟在前端摸爬滚打一段时间,发现前端的比较好的文档比较分散,特别是中文的,我平时都是ctrl+D收藏在浏览器里,以后有好的教程和综合性的文档我会更新到这里。一则可以做个记录,防止丢失。二则有需要的朋友可以来我这里找一找。 ...

    piglei 评论0 收藏0
  • React项目实战:环境搭建

    摘要:官方文档中文翻译构建用户界面的库。官方文档建议学习时以官方文档为准,中文翻译或者第三方作者的教程可以帮助你理清思路会用到的重要知识点我也会进行简明的解释,如遇到错误或者不理解的内容,欢迎实时指出。 前言 前面提到前端大统一的概念,如果感兴趣,欢迎说说自己的看法,点击前往。Web前端框架层出不穷,不可能面面俱到,这里给个小建议: 如果对Weex App感兴趣,应该选择vue框架; 如果...

    cnio 评论0 收藏0
  • React项目实战:环境搭建

    摘要:官方文档中文翻译构建用户界面的库。官方文档建议学习时以官方文档为准,中文翻译或者第三方作者的教程可以帮助你理清思路会用到的重要知识点我也会进行简明的解释,如遇到错误或者不理解的内容,欢迎实时指出。 前言 前面提到前端大统一的概念,如果感兴趣,欢迎说说自己的看法,点击前往。Web前端框架层出不穷,不可能面面俱到,这里给个小建议: 如果对Weex App感兴趣,应该选择vue框架; 如果...

    GHOST_349178 评论0 收藏0
  • react+react-router4+redux最新版构建分享

    摘要:相关配置请参考中文文档。关于的更多使用方法及理解需要详细具体讲解,涉及篇幅较大,本文暂不涉及,有兴趣可以看文档中文文档,我会整理后再单独章节分享接下来我们将编写路由组件这与有一些差别,原来的方法已经不再使用,在中或组件从中引入。       相信很多刚入坑React的小伙伴们有一个同样的疑惑,由于React相关库不断的再进行版本迭代,网上很多以前的技术分享变得不再适用。比如react-...

    weapon 评论0 收藏0
  • react+react-router+react-redux全家桶小项目开发过程分享

    摘要:项目地址下载完项目然后即可基于的项目,主要是为了学习实战。数据都是固定的,从饿了么接口临时抓的,模拟了一个的异步数据延迟,感谢饿了么。详细信息可以看上面的官方文档,我这里就简单说一下我这个项目的应用。 react-ele-webapp 项目地址 :https://github.com/kliuj/reac... run 下载完项目npm install然后npm run dev 即可 ...

    zzir 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<