react-router 的工做方式
是在組件樹頂層放一個 Router 組件,而後在組件樹中散落着不少 Route 組件(注意比 Router 少一個「r」),頂層的 Router 組件負責分析監聽 URL 的變化,在它保護傘之下的 Route 組件能夠直接讀取這些信息。Router 是「提供者」,Route是「消費者」。以下:
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { HashRouter } from 'react-router-dom';
import './index.css';
import App from './App';
ReactDOM.render((
<HashRouter><App /></HashRouter>
), document.getElementById('root'));
// App.js
import React, { Component } from 'react';
import Overview from './page/Home';
import GitHubStars from './page/GitHubInfo';
const { Content } = Layout;
class App extends Component {
constructor(props) {
super(props);
this.state = {}
}
render() {
return (
<div>
<Content>
<Switch>
<Route exact path="/" component={ Overview }/>
<Route exact path="/stars-info" component={ GitHubStars }/>
</Switch>
</Content>
</div>
);
}
}
export default App;
更進一步,Router 其實也是一層抽象,讓下面的 Route 無需各類不一樣 URL 設計的細節。 URL設計方法,至少能夠分爲兩種:
BrowserRouter
這一種很天然,好比
/
對應
Home頁
,
/about
對應
About 頁
,可是
這樣的設計須要服務器端渲染
,由於
用戶可能直接訪問任何一個 URL,服務器端必須能對 /的訪問返回 HTML,也要對 /about的訪問返回 HTML
。BrowserRouter支持這種URL。
HashRouter
這一種看起來不天然,可是實現更簡單。
只有一個路徑 /,經過 URL 後面的 # 部分來決定路由
,/#/ 對應 Home 頁,/#/about 對應 About 頁。由於URL中#以後的部分是不會發送給服務器的,因此,
不管哪一個 URL,最後都是訪問服務器的 / 路徑,服務器也只須要返回一樣一份 HTML
就能夠,
而後由瀏覽器端解析 # 後的部分,完成瀏覽器端渲染
。HashRouter支持這種URL。
注意:exact屬性和Switch組件的做用
Route 組件的 path 屬性用於匹配路徑,由於咱們須要匹配 / 到 Home,匹配 /about 到 About,因此確定須要兩個 Route,可是,咱們不能這麼寫。
<Route path='/' component={Home}/>
<Route path='/about' component={About}/>
若是按照上面這麼寫,當訪問 /about 頁面時,不光匹配 /about,也配中 /,界面上會把 Home 和 About 都渲染出來的。
解決方法,能夠在想要精確匹配的 Route 上加一個屬性 exact,或者使用 Switch 組件(能夠把 Switch 組件看作是 JavaScript 的 switch 語句,從上往下找第一個匹配的 Route,匹配中了以後,馬上就 break,不繼續這個 Switch 下其餘的 Route 匹配了):
<Switch>
<Route exact path='/' component={Home}/>
<Route path='/about' component={About}/>
</Switch>
如何選擇
由於 create-react-app 產生的應用默認不支持服務器端渲染,爲了簡單起見,咱們在下面的例子中使用 HashRouter,在實際產品中,其實最好仍是用 BrowserRouter,這樣用戶體驗更好。