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提供了
// 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';
複製程式碼
參考文章: