React Router:从V2/V3迁移到V4

官方文档:Migrating from v2/v3 to v4

React Router V4相对V2/V3几乎完全重写了,遵循 Just Component 的 API 设计理念。

react-router V4 分成了三个包:react-router-dom(for web)、react-router-native(for #native)、react-router(core)。在浏览器中,你只需使用react-router-domreact-router-domreact-router详见: ReactTraining/react-router#4648

The Router

在 React Router v3中,有 一个单独的 <Router> 组件. 它会提供一个 history 对象作为prop属性。

同时,可以使用routes prop或者children为<Router>配置route

1
2
3
4
5
6
7
8
9
// v3
import routes from './routes'
<Router history={browserHistory} routes={routes} />
// or
<Router history={browserHistory}>
<Route path='/' component={App}>
// ...
</Route>
</Router>

而在V4中,一个重大变化就是提供了数种不同的router组件。每种都会创建一个history对象。
<BrowserRouter> 创建 browser history, <HashRouter> 创建 hash history, and<MemoryRouter>创建memory history
V4取消了集中的路由配置。

1
2
3
4
5
6
7
//v4
<BrowserRouter>
<div>
<Route path='/about' component={About} />
<Route path='/contact' component={Contact} />
</div>
</BrowserRouter>

这里要注意的是,router component 只能包裹一个元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
// yes
<BrowserRouter>
<div>
<Route path='/about' component={About} />
<Route path='/contact' component={Contact} />
</div>
</BrowserRouter>

// no
<BrowserRouter>
<Route path='/about' component={About} />
<Route path='/contact' component={Contact} />
</BrowserRouter>

Routes

在V3中,<Route>不是一个真正的组件,而是作为一个标签用来创建route配置对象。

1
2
3
4
5
6
7
/// in v3 the element
<Route path='contact' component={Contact} />
// 等同于
{
path: 'contact',
component: Contact
}

使用 v4,您可以像常规的 React 程序一样布局您应用中的组件,您要根据位置(特别是其 pathname )呈现内容的任何位置,您将呈现 <Route>
在 v4,<Route> 其实是一个组件,所以无论你在哪里渲染 <Route>,它里面的内容都会被渲染。当 <Route>path 与当前的路径匹配时,它将会渲染 component,render, or children 属性中的内容,当 <Route>path 与当前的路径不匹配时,将会渲染 null。

路由嵌套

在 v3 中,<Route> 组件是作为其父 <Route> 组件的children 嵌套其中的。

1
2
3
4
<Route path='parent' component={Parent}>
<Route path='child' component={Child} />
<Route path='other' component={Other} />
</Route>

当嵌套的 <Route> 匹配时,react 元素将会使用子 <Route> 和 父 <Route>component 属性去构建,子元素将作为父元素的 children 属性。

1
2
3
<Parent {...routeProps}>
<Child {...routeProps} />
</Parent>

使用 v4,子 <Route> 会由父<Route> 呈现。

1
2
3
4
5
6
7
8
<Route path='parent' component={Parent} />

const Parent = () => (
<div>
<Route path='child' component={Child} />
<Route path='other' component={Other} />
</div>
)

on* properties

react-router v3 提供 onEnter, onUpdate, and onLeave 方法。这些方法本质上是重写(覆盖)了 react 生命周期方法。

使用 v4,你将会使用生命周期方法 通过 <Route> 渲染的组件,你可以使用 componentDidMountcomponentWillMount 代替 onEnter,你可以使用 componentDidUpdate 或者 componentWillUpdate (更或者 componentWillReceiveProps) 代替 onUpdate,你可以使用 componentWillUnmount代替 onLeave

<Switch>

在v3中,您可以指定一些子路由,并且只会渲染匹配到的第一个。

1
2
3
4
5
6
// v3
<Route path='/' component={App}>
<IndexRoute component={Home} />
<Route path='about' component={About} />
<Route path='contact' component={Contact} />
</Route>

v4 通过 <Switch> 组件提供了相似的功能,当 <Switch>被渲染时,它仅会渲染与当前路径匹配的第一个子 <Route>

1
2
3
4
5
6
7
8
// v4
const App = () => (
<Switch>
<Route exact path='/' component={Home} />
<Route path='/about' component={About} />
<Route path='/contact' component={Contact} />
</Switch>
)

<Redirect>

在V3, 如果你想从一个路径重定向到另一个, 例如从//welcome, 你可以使用<IndexRedirect >.

1
2
3
4
// v3
<Route path="/" component={App}>
<IndexRedirect to="/welcome" />
</Route>

在V4,你可以使用<Redirect>达到相同的效果。

1
2
3
4
5
6
7
8
// v4
<Route exact path="/" render={() => <Redirect to="/welcome" component={App} />} />

<Switch >
<Route exact path="/" component={App} />
<Route path="/login" component={Login} />
<Redirect path="*" to="/" />
</Switch>

PatternUtils

  • matchPattern(pattern, pathname)

在v3中,您可以使用与内部相同的匹配代码来检查路径是否匹配模式。在v4中,已被由path-to-regexp 库驱动的matchPath替代。

  • formatPattern(pattern, params)

在v3中,您可以使用Pattern Utils.format Pattern从路径模式(可能在常量或中央路由配置中)生成有效的路径以及包含名称参数的对象:

1
2
3
4
// v3
const THING_PATH = '/thing/:id';

<Link to={PatternUtils.formatPattern(THING_PATH, {id: 1})}>A thing</Link>

在V3中,您可以省略to属性或将其设置为null以创建没有href属性的锚标签。

1
2
3
4
// v3
<Link to={disabled ? null : `/item/${id}`} className="item">
// item content
</Link>

在v4中,您应该总是提供to.如果你要设置to,你可以做对其做一层封装。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// v4
import { Link } from 'react-router-dom'

const LinkWrapper = (props) => {
const Component = props.to ? Link : 'a'
return (
<Component {...props}>
{ props.children }
</Component>
)
)

<LinkWrapper to={disabled ? null : `/item/${id}`} className="item">
// item content
</LinkWrapper>


本文转载自:https://github.com/YutHelloWorld/Blog/issues/4

×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. The Router
  2. 2. Routes
  3. 3. 路由嵌套
  4. 4. on* properties
  5. 5. <Switch>
  6. 6. <Redirect>
  7. 7. PatternUtils
  8. 8. Link
,