React Router v4几乎重写了v2/v3,相比于v3变化较大,包括Router/Route的改变,组件嵌套的方式,路由的生命周期,Swicth和Redirect等组件都改变较多,新版本的react router更偏向组件化,基本上与React的思想一致。
Router
在v3中,我们使用带history属性的Router
// v3
import routes from './routes'
<Router history={browserHistory} routes={routes} />
// or
<Router history={browserHistory}>
<Route path='/' component={App}>
// ...
</Route>
</Router>
在v4中,提供了几种不同的Router组件,每个Router组件都会创建一个history
对象。
//v4
<BrowserRouter>
<div>
<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />
</div>
</BrowserRouter>
在v3中Router组件里面可以渲染多个组件
// V2 or V3
import { Router, Route, hashHistory } from 'react-router';
<Router history={hashHistory}>
<Route path='/about' component={About} />
<Route path='/contact' component={Contact} />
</Router>
而v4中,Router组件只能渲染一个组件
// 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配置对象
/// in v3 the element
<Route path='contact' component={Contact} />
// was equivalent to
{
path: 'contact',
component: Contact
}
在v4中,组件就是一个真正的组件,当path
与当前location
匹配时,就会使用rendering prop(component,render或者children)
来渲染;当path
没有匹配到时,就会渲染null。
嵌套路由
在v3中,的嵌套通过将它们作为父的children
<Route path="parent" component={Parent}>
<Route path="child" component={Child} />
<Route path="other" component={Other} />
</Route>
在v4中,只能被它的父组件渲染
<Route path="parent" component={Parent} />;
function Parent() {
return (
<div>
<Route path="child" component={Child} />
<Route path="other" component={Other} />
</div>
);
}
路由的生命周期
V3提供了onEnter
,onUpdate
和onLeaves
方法,在v4中我们需要用生命周期方法,用componentDidMount
代替onEnter
,用componentDidupdate
代替onUpdate
,用componentWillUnmount
代替onLeave
。
Switch
在v3中,我们可以指定多个子routes,只有第一个匹配的才会渲染
// v3
<Route path="/" component={App}>
<IndexRoute component={Home} />
<Route path="about" component={About} />
<Route path="contact" component={Contact} />
</Route>
v4提供了组件,当一个组件被渲染时,只有匹配当前location的第一个child 才会被渲染。
// v4
const App = () => (
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />
</Switch>
);
Redirect
在v3中,如果我们需要进行路径的跳转,比如从/
跳转到/welcome
,就需要用到IndexRedirect
。
// v3
<Route path="/" component={App}>
<IndexRedirect to="/welcome" />
</Route>
在V4中,我们可以使用 Redirect
// 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>
在v3中,Redirect
保留了查询字符串
// v3
<Redirect from="/" to="/welcome" />
// /?source=google → /welcome?source=google
在v4中,我们需要重新传递这些属性到 to属性上
// v4
<Redirect from="/" to="/welcome" />
// /?source=google → /welcome
<Redirect from="/" to={{ ...location, pathname: "/welcome" }} />
// /?source=google → /welcome?source=google
其他变化
history.push和history.replace
/ V2 or V3
history.push({
pathname: '/home',
query: {
foo: 'test',
bar: 'temp'
}
});
history.replace({
pathname: '/home',
query: {
foo: 'test',
bar: 'temp'
}
});
// V4
history.push({
pathname: '/home',
search: '?foo=test&bar=temp',
});
history.replace({
pathname: '/home',
search: '?foo=test&bar=temp',
});
可选参数
在v3中通过括号来表示可选 path="/entity/:entityId(/:parentId)"
在v4中通过一个尾随的问号来表示可选 path="/entity/:entityId/:parentId?"
props.params
// V2 or V3 获取params可以这么获取
this.props.params
// V4
this.props.match.params
location.query(查询字符串)
V4 去掉了location.query
,只能使用search
来获取,为了让其跟浏览器一样,如果想要兼容以前的location.query
,可以使用query-string
库解析一下
// V2 or V3 获取query可以这么获取
this.props.location.query
// V4 去掉了location.query,只能使用search来获取,为了让其跟浏览器一样
// 如果想要兼容以前的location.query,可以使用query-string库解析一下
// 如: queryString.parse(props.location.search)
this.props.location.search
location.action
// V2 or V3 获取location的action
this.props.location.action
// V4 去掉了location.action, 放在了history里面
history.action
获取history库
//以前获取react-router里面的history库,可以这么获取:
import {hashHistory as history} from 'react-router';
//V4
import createHashHistory as history from 'history/createHashHistory';
参考文章: