概述
react-router V4 相對於react-router V2 or V3 幾乎是重寫了, 新版的react-router更偏向於元件化(everything is component)。
V4
汲取了很多思想,路由即是元件,使路由更具宣告式,且方便組合。如果你習慣使用react
,那麼一定會很快上手新版的react-router
。
react-router V4 被一分為三: react-router-dom
(for web)、react-router-native
(for native)、react-router
(core)。但如果僅在瀏覽器中使用的話,一般只需要用到react-router-dom
就可以了。
改動點
1. Router/Route 的改變
// V2 or V3
import { Router, Route, hashHistory } from `react-router`;
<Router history={hashHistory}>
<Route path=`/foo` component={Foo} />
<Route path=`/bar` component={Bar} />
</Router>
// V4 Router元件裡只能渲染一個元件
import {
HashRouter as Router,
Route
} from `react-router-dom`;
<Router>
<div>
<Route path=`/foo` component={Foo} />
<Route path=`/bar` component={Bar} />
</div>
</Router>
2. 元件巢狀
// V2 or V3 路由元件巢狀
import { Router, Route, hashHistory } from `react-router`;
<Router history={hashHistory}>
<Route path=`/` component={App}>
<Route path=`foo` component={Foo} />
<Route path=`bar` component={Bar} />
</Route>
</Router>
// V4 Router 的路由元件巢狀
import {
HashRouter as Router,
Route,
Switch
} from `react-router-dom`;
<Router>
<Route path="/" component={(props) => (
<App {...props}>
<Switch>
<Route path=`/foo` component={Foo} />
<Route path=`/bar` component={Bar} />
</Switch>
</App>
)}/>
</Router>
3. 路由的生命週期
在react-router V4
中去掉了on****
的路由生命週期的鉤子,但是你可以在元件中用componentDidMount
或 componentWillMount
代替 onEnter
,可以用componentWillUpdate
或 componentWillReceiveProps
代替 onUpdate
,你可以用componentWillUnmount
代替 onLeave
。
4. Link
// V2 or V3
import { Link } from `react-router`;
// V4
import { Link } from `react-router-dom`;
5. history.push and 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`,
});
6. props.params
// V2 or V3 獲取params可以這麼獲取
this.props.params
// V4
this.props.match.params
7. location.query
// 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
8. location.action
// V2 or V3 獲取location的action
this.props.location.action
// V4 去掉了location.action, 放在了history裡面
history.action
9.關於history
以前獲取react-router裡面的history庫,可以這麼獲取:
import {hashHistory as history} from `react-router`;
react-router V4:
import createHashHistory as history from `history/createHashHistory`;
相容處理
因為要從react-router V2
完全遷移到react-router V4
工作量還是挺大的,一下子難以完全遷移,所以對某些地方做了相容處理。
history
import _ from `lodash`;
import queryString from `query-string`;
function processHistory(history) {
const _push = history.push;
const _replace = history.replace;
history.push = function (one) {
if (!_.isPlainObject(one)) {
return _push.apply(this, arguments);
}
const o = Object.assign({}, one);
if (o.query) {
o.search = queryString.stringify(o.query);
}
_push.apply(this, [o]);
};
history.replace = function (one) {
if (!_.isPlainObject(one)) {
return _replace.apply(this, arguments);
}
const o = Object.assign({}, one);
if (o.query) {
o.search = queryString.stringify(o.query);
}
_replace.apply(this, [o]);
};
return history;
}
export default processHistory;
props
import queryString from `query-string`;
const processReactRouterProps = (props) => {
const newProps = Object.assign({}, props);
newProps.location.query = queryString.parse(props.location.search);
newProps.location.action = newProps.history.action;
newProps.params = props.match.params || {}; // 不止 || 是否有意義
return newProps;
}
export default processReactRouterProps;
參考資料: