React Router
文档已经过时! 请查看最新版本 http://rackt.github.io/react-router/
原文: https://github.com/rpflorence/react-router/blob/master/README.md
为 React 定制的完整 routing 模块.
功能
- 嵌套的 View 映射到嵌套的 Routes
- route 层级模块化的建构
- 完全异步的 transition 钩子
- transition 的 abort / redirect / retry
- 动态的片段
- Query 参数
- 当路由被激活时, 自动给 Links 加
.active
class - 多个顶级 routes
- Hash 或者 HTML5 历史的 url
查看 examples
目录来了解前面复杂的 UI 和工作流是怎么创建的.
安装
sh
npm install react-nested-router # or bower install react-router
这个模块是用 CommonJS 模块写的, 如果你是用 Browserify, Webpack, 这之类的,
你可以当作是其他从 npm 安装的模块一样处理.
在 Bower 上还有一个 UMD 构建的版本, 通过 window.ReactRouter
引用模块.
用法
var Route = require('react-nested-router').Route;
React.renderComponent((
<Route handler={App}>
<Route name="about" handler={About}/>
<Route name="users" handler={Users}>
<Route name="user" path="/user/:userId" handler={User}/>
</Route>
</Route>
), document.body);
如果 JSX 对你来说不算美味的话:
js
React.renderComponent(( Route({handler: App}, Route({name: "about", handler: About}), Route({name: "users", handler: Users}, Route({name: "user", path: "/user/:userId", handler: User}) ) ) ), document.body);
url 会被映射到最深的 route, 随后所有上方层级的 routes 会被激活,
对应的handlers
(等同 React components)会被渲染.每个 handler 会接收到一个
params
属性, 包含从 url 中匹配到的参数, 比如:userId
.handler 还好收到一个
query
属性, 是当前的 query 参数的词典.父级的 routes 会接收到一个
activeRouteHandler
属性, 是一个函数, 用来渲染激活的子元素.
应用的其余部分是这样的:
js
var Link = require('react-nested-router').Link; var App = React.createClass({ render: function() { return ( <div> <ul> <li><Link to="about">About</Link></li> <li><Link to="users">Users</Link></li> <li><Link to="user" userId="123">User 123</Link></li> </ul> <this.props.activeRouteHandler/> </div> ); } }); var About = React.createClass({ render: function() { return <h2>About</h2> ; } }); var Users = React.createClass({ render: function() { return ( <div> <h2>Users</h2> <this.props.activeRouteHandler/> </div> ); } }); var User = React.createClass({ render: function() { return <div>{this.props.params.userId}</div> } });
要更好地理解 activeRouteHandler
做了什么, 也许一个没有 router 的例子会有用.
比如某个场景 /users/2
被选中, 你不用 router 来渲染, 看起来像是这样:
js
render: function() { var user = <User params={{userId: 2}}/>; var users = <User activeRouteHandler={user}/>; return <App activeRouteHandler={users}/>; }
而 router 可以帮你管理 view 的层级关系.
这个方案的好处
惊人的创建页面的生产力 - 用户访问 route 只有一个场景: 渲染.
每个 UI 都有 layer(或者嵌套), 可能是简单的导航栏, 或者多层的主从结构.
把嵌套的 routes 和对应嵌套的 View 耦合在一起, 减去了很多切换过程中两者纠缠的工作.
添加新的页面就更快了.快速理解应用结构 - 当 routes 是在一个地方写清楚的, 开发者很快能从整体看清全局.
这像是一个基础的 sitemap. 别的办法也没法把应用的那么多信息展示得更快了.代码的可操作性 - 当有其他的开发者来修复某个 url 的 bug, 他只要做:
1) 看懂 route 的设置, 2) 找到对应 route 的 handler.
每个应用的入口都会在这些 routes 当中展示出来.url 是你第一件想的事情, 而不是回头想的事情 - 借助 React 嵌套的 router,
配置 url 以前你是不会得到那么一个页面的. 幸运的是, 这个方案开发小略非常高.
相关的模块
- https://github.com/bjyoungblood/rnr-constrained-route - 验证 route handler 的 path 和参数.
API
Route (component)
配置 component, 声明应用的 routes 和 View 的层级.
Props(属性)
location - 这个方法用在初始化 router 时页面的导航.
可以是 "hash" 表示在 url 当中使用 hash 并监听 hashchange
事件,
或者 "history" 表示使用 HTML5 History API.
这个属性只能在宣染尽页面的第一层的 route 当中使用.
默认值是 "hash".
name - route 的名字, 在 Link
component 和 router 的 transition 方法当中使用.
path - 在 url 当中使用的 path, 支持动态生成的片段.
如果这个属性没有被定义(undefined
), 这个 path 将会被定义为 name
的值.
这个 path 永远是绝对路径, 即便开头的斜线 /
没有加上.
嵌套的 routes 不会从父级继承 path 的内容.
handler - 当 route 匹配时会被渲染的 component.
子元素
routes 是可以嵌套的. 当子级的 route 匹配了,
父级 route 的 handler 会有个子级 route 的 handler 的实例,
可以通过 this.props.activeRouteHandler()
调用.
你可以在父级当中渲染, 可以传入任何额外需要的属性.
例子
xml
<Route handler={App}> <!-- path 被自动赋值到 name 上, 因为 name 省略了 --> <Route name="about" handler={About}/> <Route name="users" handler={Users}> <!-- note the dynamic segment in the path --> <!-- 注意 path 当中的动态片段 --> <Route name="user" handler={User} path="/user/:id"/> </Route> </Route>
或者不用 JSX:
js
Route({handler: App}, Route({name: 'about', handler: About}), Route({name: 'users', handler: Users}, Route({name: 'user', handler: User, path: '/user/:id'}) ) );
Route Handler (用户定义的 component)
传给 route 的 handler
属性的另一个 component, 当 route 被激活时会渲染到页面上.
这些 components 上会有一些特殊的属性和一些静态的方法.
Props(属性)
this.props.activeRouteHandler(extraProps) - 活跃的子节点的 route handler.
在渲染方法当中通过这个渲染子级的 route, 传入额外需要的参数.
this.props.params - 当 route 中存在形如 <Route path="users/:userId"/>
的动态片段,
这些动态的数据就可以在比如 this.props.params.userId
当中吊桶.
this.props.query - url 的 query 参数.
静态方法 (transition 的钩子)
你可以在 route handlers 上定义静态方法, 方法将在 route 的 transition 进行时被调用.
willTransitionTo(transition, params) - 在 route 即将被渲染时调用.
这样你有有机会去中止 transition 过程.
你也可以返回一个 promise, 这样整个 route 层级在继续执行前会先等待 promise 被完成.
这一点对服务端渲染非常有用, 你会需要在 handler 被渲染前构建一些数据.
willTransitionFrom(transition, component) - 在 route transition 开始时调用,
这样就有机会去中止 transition.
这里的 component
是当前的 component, 你可能会需要检查 state 来决定是否运行 transition.
Transition (对象)
transition.abort() - 中止 transition
transition.redirect(to, params, query) - 重定向到另一个 route
transition.retry() - 重试某个 transition
例子
js
var Settings = React.createClass({ statics: { willTransitionTo: function(transition, params) { return auth.isLoggedIn().then(function(loggedIn) { if (!loggedIn) return; transition.abort(); return auth.logIn({transition: transition}); // in auth module call `transition.retry()` after being logged in }); }, willTransitionFrom: function(transition, component) { if (component.formHasUnsavedData())) { if (!confirm('You have unsaved information, are you sure you want to leave this page?')) { transition.abort(); } } } } //... });
Link (Component)
创建一个锚点元素, 链接到应用的一个 route. 当 route 匹配时自动增加 active
class.
如果你改变 route 的 path, 不一定要改变你写的 links.
Properties(属性)
to - 链接的到的 route 的名字.
query - 对象, 添加到 link 上的 query 参数.
从 route handler 上通过 this.props.query
来访问 query 参数.
[param] - route 定义时传入的任何参数会被传入 link 的属性.
例子
当 route 是 <Route name="user" path="/users/:userId"/>
:
xml
<Link to="user" userId={user.id} params={{foo: bar}}>{user.name}</Link> <!-- 根据 route 是否被激活, router 变成其中的一个 --> <a href="/users/123?foo=bar" class="active">Michael</a> <a href="#/users/123?foo=bar">Michael</a>
顶层的静态方法
router 有几个顶层的方法可以用来对应用进行导航.
js
var Router = require('react-nested-router')
transitionTo(routeName, [params[, query]]) - 通过程序 transition 到新的 route.
js
Router.transitionTo('user', {id: 10}, {showAge: true}); Router.transitionTo('about');
replaceWith(routeName, [params[, query]]) - 通过程序把当前的 route 替换为新的 route.
但是不在浏览器的历史里增加记录.
js
Router.replaceWith('user', {id: 10}, {showAge: true}); Router.replaceWith('about');
goBack() - 通过程序返回前一个 route 并从浏览器历史记录删去最近的一条记录.
js
Router.goBack();
开发
查看 CONTRIBUTING
感谢 Ember
这个模块很大程度上收到 Ember.js router API 的启发.
一般来说, 这是个 Ember router API 在 React 当中的一个翻译.
深深感谢 Ember 团队他们已经把最难的部分解决了.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。