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,这样用户体验更好。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。