React Router 4.0 (以下简称 RR4) 已经正式发布,它遵循React的设计理念,即万物皆组件。所以 RR4 只是一堆 提供了导航功能的组件(还有若干对象和方法),具有声明式(引入即用),可组合性的特点。http://www.jianshu.com/p/e3adc9b5f75c
RR4 本次采用单代码仓库模型架构(monorepo),这意味者这个仓库里面有若干相互独立的包,分别是:
react-router
React Router 核心react-router-dom
用于 DOM 绑定的 React Routerreact-router-native
用于 React Native 的 React Routerreact-router-redux
React Router 和 Redux 的集成react-router-config
静态路由配置的小助手本文主要讨论在 web app 中如何使用使用 RR4。
在 React 的使用中,我们一般要引入两个包,react
和 react-dom
,那么 react-router
和react-router-dom
是不是两个都要引用呢?
非也,坑就在这里。他们两个只要引用一个就行了,不同之处就是后者比前者多出了
这样的 DOM 类组件。
因此我们只需引用 react-router-dom
这个包就行了。当然,如果搭配 redux ,你还需要使用 react-router-redux
。
what is the diff between react-router-dom & react-router?
一个使用了 HTML5 history API 的高阶路由组件,保证你的 UI 界面和 URL 保持同步。此组件拥有以下属性:
basename: string
作用:为所有位置添加一个基准URL
使用场景:假如你需要把页面部署到服务器的二级目录,你可以使用 basename
设置到此目录。
"/minooo" />
// 最终渲染为
getUserConfirmation: func
作用:导航到此页面前执行的函数,默认使用 window.confirm
使用场景:当需要用户进入页面前执行什么操作时可用,不过一般用到的不多。
const getConfirmation = (message, callback) => {
const allowTransition = window.confirm(message)
callback(allowTransition)
}
'Are you sure?', yourCallBack)} />
forceRefresh: bool
作用:当浏览器不支持 HTML5 的 history API 时强制刷新页面。
使用场景:同上。
const supportsHistory = 'pushState' in window.history
keyLength: number
作用:设置它里面路由的 location.key
的长度。默认是6。(key的作用:点击同一个链接时,每次该路由下的 location.key
都会改变,可以通过 key 的变化来刷新页面。)
使用场景:按需设置。
12} />
children: node
作用:渲染唯一子元素。
使用场景:作为一个 Reac t组件,天生自带 children 属性。
尝试一下
Hash history 不支持 location.key
和 location.state
。另外由于该技术只是用来支持旧版浏览器,因此更推荐大家使用 BrowserRouter,此API不再作多余介绍。
render methods 分别是:
应该只使用一种 render method ,大部分情况下你将使用 component
。props 分别是:
match
location
history
component
只有当访问地址和路由匹配时,一个 React component 才会被渲染,此时此组件接受 route props (match, location, history)。
当使用 component
时,router 将使用 React.createElement
根据给定的 component 创建一个新的 React 元素。这意味着如果你使用内联函数(inline function)传值给 component
将会产生不必要的重复装载。对于内联渲染(inline rendering), 建议使用 render
prop。
"/user/:username" component={User} />
const User = ({ match }) => {
return <h1>Hello {match.params.username}!h1>
}
render: func
此方法适用于内联渲染,而且不会产生上文说的重复装载问题。
// 内联渲染
"/home" render={() => Home
// 包装 组合
const FadingRoute = ({ component: Component, ...rest }) => (
(
)} />
)
children: func
有时候你可能只想知道访问地址是否被匹配,然后改变下别的东西,而不仅仅是对应的页面。
const ListItemLink = ({ to, ...rest }) => (
(
)}
)
path: string
任何可以被 path-to-regexp解析的有效 URL 路径
"/users/:id" component={User} />
如果不给path,那么路由将总是匹配。
exact: bool
如果为 true,path 为 '/one' 的路由将不能匹配 '/one/two',反之,亦然。
strict: bool
对路径末尾斜杠的匹配。如果为 true。path 为 '/one/' 将不能匹配 '/one' 但可以匹配 '/one/two'。
如果要确保路由没有末尾斜杠,那么 strict 和
exact 都必须同时为 true
尝试一下
为你的应用提供声明式,无障碍导航。
to: string
作用:跳转到指定路径
使用场景:如果只是单纯的跳转就直接用字符串形式的路径。
"/courses" />
to: object
作用:携带参数跳转到指定路径
作用场景:比如你点击的这个链接将要跳转的页面需要展示此链接对应的内容,又比如这是个支付跳转,需要把商品的价格等信息传递过去。
pathname: '/course',
search: '?sort=name',
state: { price: 18 }
}} />
replace: bool
为 true 时,点击链接后将使用新地址替换掉上一次访问的地址,什么意思呢,比如:你依次访问 '/one' '/two' '/three' ’/four' 这四个地址,如果回退,将依次回退至 '/three' '/two' '/one' ,这符合我们的预期,假如我们把链接 '/three' 中的 replace 设为 true 时。依次点击 one two three four 然后再回退会发生什么呢?会依次退至 '/three' '/one'! 为此我做了个在线 demo,大家可以调试体会一下 !
另外你能想到这个 prop 的用途是什么呢?有人说在用 路由 做选项卡时候会用到。欢迎留言讨论!
尝试一下
这是 的特殊版,顾名思义这就是为页面导航准备的。因为导航需要有 “激活状态”。
activeClassName: string
导航选中激活时候应用的样式名,默认样式名为 active
"/about"
activeClassName="selected"
>MyBlog</NavLink>
activeStyle: object
如果不想使用样式名就直接写style
"/about"
activeStyle={{ color: 'green', fontWeight: 'bold' }}
>MyBlog</NavLink>
exact: bool
若为 true,只有当访问地址严格匹配时激活样式才会应用
strict: bool
若为 true,只有当访问地址后缀斜杠严格匹配(有或无)时激活样式才会应用
isActive: func
决定导航是否激活,或者在导航激活时候做点别的事情。不管怎样,它不能决定对应页面是否可以渲染。
尝试一下
只渲染出第一个与当前访问地址匹配的
或
。
思考如下代码,如果你访问 /about
,那么组件 About User Nomatch 都将被渲染出来,因为他们对应的路由与访问的地址 /about
匹配。这显然不是我们想要的,我们只想渲染出第一个匹配的路由就可以了,于是
应运而生!
"/about" component={About}/>
也许你会问,为什么 RR4 机制里不默认匹配第一个符合要求的呢,答:这种设计允许我们将多个
另外,
对于转场动画也非常适用,因为被渲染的路由和前一个被渲染的路由处于同一个节点位置!
<Switch>
{/* 用了Switch 这里每次只匹配一个路由,所有只有一个节点。 */}
<Route/>
<Route/>
Switch>
</Fade>
>
<Route/>
{/* 不用 Switch 这里可能就会匹配多个路由了,即便匹配不到,也会返回一个null,使动画计算增加了一些麻烦。 */}
</Fade>
children: node
下的子节点只能是
或
元素。只有与当前访问地址匹配的第一个子节点才会被渲染。
元素用它们的 path
属性匹配,
元素使用它们的 from
属性匹配。如果没有对应的 path
或 from
,那么它们将匹配任何当前访问地址。
尝试一下
渲染时将导航到一个新地址,这个新地址覆盖在访问历史信息里面的本该访问的那个地址。
to: string
重定向的 URL 字符串
to: object
重定向的 location 对象
push: bool
若为真,重定向操作将会把新地址加入到访问历史记录里面,并且无法回退到前面的页面。
from: string
需要匹配的将要被重定向路径。
尝试一下
当用户离开当前页面前做出一些提示。
message: string
当用户离开当前页面时,设置的提示信息。
"确定要离开?" />
message: func
当用户离开当前页面时,设置的回掉函数
(
`Are you sue you want to go to ${location.pathname}?`
)} />
when: bool
通过设置一定条件要决定是否启用 Prompt
尝试一下
histoty 是 RR4 的两大重要依赖之一(另一个当然是 React 了),在不同的 javascript 环境中, history 以多种能够行驶实现了对会话(session)历史的管理。
我们会经常使用以下术语:
history 对象通常具有以下属性和方法:
history 对象是可变的,因为建议从
的 prop 里来获取 location,而不是从 history.location 直接获取。这样可以保证 React 在生命周期中的钩子函数正常执行,例如以下代码:
class Comp extends React.Component {
componentWillReceiveProps(nextProps) {
// locationChanged
const locationChanged = nextProps.location !== this.props.location
// 错误方式,locationChanged 永远为 false,因为history 是可变的
const locationChanged = nextProps.history.location !== this.props.history.location
}
}
location 是指你当前的位置,将要去的位置,或是之前所在的位置
{
key: 'sdfad1'
pathname: '/about',
search: '?name=minooo'
hash: '#sdfas',
state: {
price: 123
}
}
在以下情境中可以获取 location 对象
Route component
中,以 this.props.location 获取Route render
中,以 ({location}) => () 方式获取Route children
中,以 ({location}) => () 方式获取withRouter
中,以 this.props.location 的方式获取location 对象不会发生改变,因此可以在生命周期的回调函数中使用 location 对象来查看当前页面的访问地址是否发生改变。这种技巧在获取远程数据以及使用动画时非常有用
componentWillReceiveProps(nextProps) {
if (nextProps.location !== this.props.location) {
// 已经跳转了!
}
}
可以在不同情境中使用 location:
match 对象包含了
在以下情境中可以获取 match 对象
Route component
中,以 this.props.match获取Route render
中,以 ({match}) => () 方式获取Route children
中,以 ({match}) => () 方式获取withRouter
中,以 this.props.match的方式获取当一个 Route 没有 path 时,它会匹配一切路径。