页面路由——React-Router
React-Router
简介
React Router 是一个基于 React 之上的强大路由库,它可以让你向应用中快速地添加视图和数据流,同时保持页面与 URL 之间的同步。
使用 React Router
import React from 'react'
import { render } from 'react-dom'
// 首先我们需要导入一些组件...
import { Router, Route, Link } from 'react-router'
// 然后我们从应用中删除一堆代码和
// 增加一些 <Link> 元素...
const App = React.createClass({
render() {
return (
<div>
<h1>App</h1>
{/* 把 <a> 变成 <Link> */}
<ul>
<li><Link to="/about">About</Link></li>
<li><Link to="/inbox">Inbox</Link></li>
</ul>
{/*
接着用 `this.props.children` 替换 `<Child>`
router 会帮我们找到这个 children
*/}
{this.props.children}
</div>
)
}
})
// 最后,我们用一些 <Route> 来渲染 <Router>。
// 这些就是路由提供的我们想要的东西。
React.render((
<Router>
<Route path="/" component={App}>
<Route path="about" component={About} />
<Route path="inbox" component={Inbox} />
</Route>
</Router>
), document.body)如果你不熟悉 JSX,也可以用普通对象来替代。
获取 URL 参数
为了从服务器获取 message 数据,我们首先需要知道它的信息。当渲染组件时,React Router 会自动向 Route 组件中注入一些有用的信息,尤其是路径中动态部分的参数。
也可以通过 query 字符串来访问参数。比如访问 /foo?bar=baz可以通过访问 this.props.location.query.bar 从 Route 组件中获取 'baz'的值
基础

添加首页
当URL为/时,我们想渲染一个在 App中的组件。不过此时,App 的 render中的this.prop.children还是undefined。这种情况下我们可以使用 IndexRoute来设置一个默认页面。
让 UI 从 URL 中解耦出来
通过在定义 path 中使用 /messages/:id 替换 messages/:id 在多层前套路由中使用绝对路径的能力让我们对 URL 拥有绝对的掌握。我们无需在 URL 中添加更多的层级。
兼容旧的 URL
使用 <Redirect> 使URL重定向。
进入和离开 Hook
Route 可以定义 onEnter 和 onLeave 两个 hook,这些 hook 会在页面跳转确认时触发一次。这些 hook 对于一些情况非常的有用,例如权限验证或者在路由跳转前将一些数据持久化保存起来。
在路由跳转过程中
onLeave会在所有将离开的路由中触发,从最下层的路由开始直到最外层路由结束。onEnter会在将进入的路由时触发。
替换配置方式
如果你不想使用 JSX,也可以直接使用原生的 route 数组对象。
路由匹配原理
路由拥有三个属性来决定是否匹配一个URL
嵌套关系
路径语法
优先级
嵌套关系
当一个给定的 URL 被调用时,整个集合中(命中的部分)都会被渲染。嵌套路由被描述成一种树形结构
路径语法
匹配一个(或一部分)URL的一个字符串模式。大部分的路由路径都可以直接按照字面量理解,除了下边的特殊符号
:paramName- 匹配一段位于/、?或#之后的URL()- 在它内的内容被认为是可选的*- 匹配任意字符直到命中下一个字符或者整个 URL 的末尾
优先级
路由算法会根据定义的顺序自顶向下匹配路由
Histories
React Router是建立在 history 上的。简而言之,一个 history 知道如何去监听浏览器地址栏的变化,并解析这个 URL 转化为 location 对象,然后 router 使用它匹配到路由,最后正确的渲染页面。
browserHistory
hashHistory
createMemoryHistory
使用
browserHistory
他使用浏览器中 History API 用于处理 URL
服务器需要做好处理 URL 的准备。处理应用启动最初的/这样的请求是没问题的,但当用户来回跳转并在/account/123刷新时,服务器就会收到来自 account/123的请求,这时需要处理这个 URL 并响应对应的 JavaScript 代码。
hashHistory
Hash History 使用 URL 中的 hash # 部分去创建形如example.com/#/some/path 的路由。
对比
Hash History 不需要服务器任何配置就可以运行,但是我们不推荐在实际线上环境中使用,因为每一个 web 应用都应该渴望使用 browserHistory。
传递参数
当一个 History 通过应用程序中的 push 或 replace跳转时,他可以在新的 location中存储 location state而不显示在 URL 中,这就像是在一个 HTML 中 post 的表单数据。
createMemoryHistory
Memory History 不会在地址栏被操作或读取。同时它也非常适合测试和其他渲染环境
和另外两种 history 的一点不同是必须创建它,这种方式便于测试。
使用
默认路由 (IndexRoute) 与 IndexLink
(IndexRoute) 与 IndexLink默认路由 (IndexRoute)
Index Links
如果你在这个 app 中使用 <Link to="/">Home</Link> , 它会一直处于激活状态,因为所有的 URL 的开头都是 / 。 这确实是个问题,因为我们仅仅希望在 Home 被渲染后,激活并链接到它。
如果需要在 Home 路由被渲染后才激活的指向 / 的链接,请使用 <IndexLink to="/">Home</IndexLink>
高级用法

动态路由
React Router 适用于小型网站,也可以支持大型网站。
对于大型应用来说,一个首当其冲的问题就是所需加载的 JavaScript 的大小。程序应当只加载渲染页所需的 JavaScript。
路由是个非常适于做代码分拆的地方:他的责任就是配置好每个 view
React Router 里的路径匹配以及组件加载都是异步完成,不仅允许你延迟加载组件,并且可以延迟加载路由配置。在首次加载包中你只需要有一个路径定义,路由会自动解析剩下的路径。
Route 可以定义 getChildRoutes,getIndexRoute和getComponents这几个函数。他们都是异步执行,并且只有在需要的时候才被调用。称之为“逐渐匹配”。
匹配 URL 并只加载该 URL 对应页面所需的路径配置和组件。
跳转前确认
React Router 它提供一个 routerWillLeave 钩子,使得组件可以拦截正在发生的跳转,或在离开 route 前提示用户。
return false取消此次跳转return返回提示信息,在离开 route前提示用户进行确认。
通过在 route 组件中引入 Lifecycle mixin 来安装这钩子
服务端渲染
服务端渲染与客户端渲染有些许不同
发生错误时发送一个 500 的响应
需要重定向时发送一个 30x 的响应
在渲染之前获得数据(用 router 帮你完成这点)
为了迎合这一需求,需要在 <Router />API 下一层使用
使用
match在渲染之前根据 location 匹配 route使用
RoutingContext同步渲染route组件
组件生命周期
路由切换时,组件生命周期的变化情况
1.当用户打开应用 '/' 页面
APP
componentDidMount
Home
componentDidMount
Invoice
N/A
Account
N/A
2.当用户从 '/'跳转到 '/invoice/123'
App
componentWillReceiveProps, componentDidUpdate
Home
componentWillUnmount
Invoice
componentDidMount
Account
N/A
App 从 router 中接收到新的 props,所以触发了两个生命周期方法
Home 不再被渲染,所以它将被移除
Invoice 首次被挂载
3.当用户从 /invoice/123 跳转到 /invoice/789
App
componentWillReceiveProps, componentDidUpdate
Home
N/A
Invoice
componentWillReceiveProps, componentDidUpdate
Account
N/A
4.当从 /invoice/789 跳转到 /accounts/123
App
componentWillReceiveProps, componentDidUpdate
Home
N/A
Invoice
componentWillUnmount
Account
componentDidMount
获取数据
我们在 Invoice 组件里实现一个简单的数据获取功能
最后更新于