路由理解
- 当使用
hash
或history
的方式去改变网址路径(path)
时,并不会刷新网页或发出请求 - 通过监听
hash
或history
的变化来动态的切换组件的显示 - 据此,可以维护
path(路径)
跟component(组件)
的 一对一的路由 - 而管理这些
route(路由)
的就是router(路由器)
简单 demo
-
主要目录结构
-
index.js
import React from 'react'; import ReactDOM from 'react-dom'; import {BrowserRouter} from 'react-router-dom' // 导出 history 模式的路由器 import App from './App'; // 整个应用都要受到该路由器的管理,因此要使它包裹 App 标签 ReactDOM.render( <BrowserRouter> <App /> </BrowserRouter>, document.getElementById('root') );
-
App.js
import React, { Component } from 'react' import {Link, Route} from 'react-router-dom' import Home from './pages/Home' // 导入组件 import About from './pages/About' // 当 点击 Link 标签,path 更改后,对应的组件就会被显示 export default class App extends Component { render() { return ( <div> <h1>header</h1> <Link to="/home">Home</Link> {/* Link 用于更改 path */} <Link to="/about">About</Link> <Route path="/home" component={Home}/> {/* Route 用于注册路由 */} <Route path="/about" component={About}/> </div> ) } }
-
Home/index.jsx
import { Component } from 'react' export default class Home extends Component { render() { return ( <h3> Home </h3> ) } }
-
About/index.jsx
import { Component } from 'react' export default class About extends Component { render() { return ( <h3> About </h3> ) } }
-
页面效果
路由标签
-
Link
用于更改path
-
Route
用于注册路由 -
BrowserRouter
为history
模式路由器,需要包裹在App
标签外,以保证所有路由都受它管理 -
HashRouter
为hash
模式路由器,需要包裹在App
标签外,以保证所有路由都受它管理 -
NavLink
: 相比于Link
, 在激活时会应用active
类名,该类名可以通过activeClassName
属性进行指定<NavLink activeClassName="active" path="/about" component={About}>About</NavLink>
-
Switch
: 选择路由时,匹配成功就停止不再继续向下匹配,如下<!-- 如果当前 路径为 /home 那么最后两个组件都会被显示 --> <Route path="/about" component={About} /> <Route path="/home" component={Home} /> <Route path="/home" component={Home} /> <!-- 如果使用 Switch 包裹路由 那么在第一次成功匹配后,就不会再继续向下匹配,因此只显示第二个组件--> <Switch> <Route path="/about" component={About} /> <Route path="/home" component={Home} /> <Route path="/home" component={Home} /> </Switch>
-
Redirect
: 重定向,当所有路由都匹配不上时,用于兜底
<Switch>
<Route path="/about" component={About} />
<Route path="/home" component={Home} />
<!-- 当其他路由都匹配不上时,将当前路由路径重定向到 /home -->
<Redirect to="/home" />
</Switch>
- todos 待补充
严格匹配跟模糊匹配
- 假设当前路由路径是
/home/a/b/c
,那么 以下路由会显示,因为/home
模糊匹配成功
<Route path="/home" component={Home} />
- 而如果开启严格匹配(
指定exact
),则必须路由路径完全相同
<Route exact path="/home" component={Home} /> // 不显示
<Route exact path="/home/a/b/c" component={Home} /> // 显示
路由嵌套
- 当使用多级嵌套路由时,子路由的路径,需要包含父级的路径
- 每当路由路径发生变化时,
react
,都会从最开始注册的路由,到最后注册的路由,依次进行匹配
<Route path="/home/news" component={news} />
路由参数
params 参数
<Link to={`/home/news/${msg.id}/${msg.detail}`}>news</Link>
<!-- id 、 detail 会被解释成参数,并传入this.props中 -->
<Route path="/home/news/:id/:detail" component={news}/>
search 参数
- 类似于
query
参数,需要使用 react 项目默认下载的querystring
库进行解析
<Link to={`/home/news?id=${msg.id}&detail=${msg.detail}`}>news</Link>
<!-- 正常注册路由即可 -->
<Route path="/home/news" component={news}/>
state 参数
<Link to={{pathname="/home/news", state: {id: msg.id, detail: msg.detail}}}>news</Link>
<!-- 正常注册路由即可 -->
<Route path="/home/news" component={news}/>
- 如果 使用
HashRouter
,那么在刷新的时候state
参数会丢失,而BrowserRouter
,不会,因为后者将state
保存在history
对象中
路由导航模式
- 路由有两种导航方式:
push
、replace
- 默认情况是
push
方式, 可以使用如下方式修改为replace
<Link replace to="/home/news">news</Link>
编程式路由导航
- 借助
this.props.history
上的方法进行导航
this.props.history.push(pathname, state)
this.props.history.replace(pathname, state)
this.props.history.go(n)
this.props.history.goBack()
this.props.history.goForward()
withRouter
- 一般组件在
this.props
没有history
对象,因此无法操作路由 - 因此,可以使用
withRouter
函数,对一般组件进行包装,使其拥有路由组件的方法和属性
import {withRouter} from 'react-router-dom'
class Header extends Component {
...
}
export default withRouter(Header) // 导出包装后的对象