react-router-dom的理解
- react的一个插件库。
- 专门用来实现一个SPA应用。
- 基于react的项目基本都会用到此库。
react-router-dom相关API
内置组件
<BrowserRouter>
<HashRouter>
<Route>
<Redirect>
<Link>
<NavLink>
<Switch>
其它
- history对象
- match对象
- withRouter函数(将一般组件变成路由组件)
基本路由使用
下载
1
| npm install --save react-router-dom
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import React from 'react'
import ReactDOM from 'react-dom' import {BrowserRouter} from 'react-router-dom'
import App from './App'
ReactDOM.render( <BrowserRouter> <App/> </BrowserRouter>, document.getElementById('root') )
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import React, { Component } from 'react' import {Link,Route} from 'react-router-dom' export default class App extends Component { render() { return ( <div> {/* 原生html中,靠<a>跳转不同的页面 */} {/* <a className="list-group-item" href="./about.html">About</a> <a className="list-group-item active" href="./home.html">Home</a> */}
{/*导航区 在React中靠路由链接实现切换组件--编写路由链接 */} <Link className="list-group-item" to="/about">About</Link> <Link className="list-group-item" to="/home">Home</Link> {/*展示区 注册路由 */} <Route path="/about" component={About}/> <Route path="/home" component={Home}/> </div> ) } }
|
路由组件与一般组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 1.写法不同: 一般组件:<Demo/> 路由组件:<Route path="/demo" component={Demo}/> 2.存放位置不同: 一般组件:components 路由组件:pages 3.接收到的props不同: 一般组件:写组件标签时传递了什么,就能收到什么 路由组件:接收到三个固定的属性 history: go: ƒ go(n) goBack: ƒ goBack() goForward: ƒ goForward() push: ƒ push(path, state) replace: ƒ replace(path, state) location: pathname: "/about" search: "" state: undefined match: params: {} path: "/about" url: "/about"
|
NavLink
NavLink可以实现路由链接的高亮,通过activeClassName指定样式名
1 2
| <NavLink activeClassName="atguigu" className="list-group-item" to="/home">Home</NavLink> <NavLink activeClassName="atguigu" className="list-group-item" to="/about">About</NavLink>
|
Switch
- 通常情况下,path和component是一一对应的关系。
- Switch可以提高路由匹配效率(单一匹配)。
1 2 3 4 5 6
| {} <Switch> <Route path="/about" component={About}/> <Route path="/home" component={Home}/> <Route path="/home" component={Test}/> </Switch>
|
Redirect
1 2 3 4 5 6 7
|
<Switch> <Route path="/about" component={About}/> <Route path="/home" component={Home}/> <Redirect to="/about"/> </Switch>
|
withRouter
withRouter可以加工一般组件,让一般组件具备路由组件所特有的API
withRouter的返回值是一个新组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import React, { Component } from 'react' import {withRouter} from 'react-router-dom'
class Header extends Component {
render() { return ( <div > </div> ) } }
export default withRouter(Header)
|
嵌套路由
1 2 3 4 5 6 7 8 9 10 11 12 13
|
<MyNavLink to="/home/news">News</MyNavLink> <MyNavLink to="/home/message">Message</MyNavLink>
{} <Switch> <Route path="/home/news" component={News}/> <Route path="/home/message" component={Message}/> <Redirect to="/home/news"/> </Switch>
|
向路由组件传递参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 1.params参数 路由链接(携带参数):<Link to='/demo/test/tom/18'}>详情</Link> 注册路由(声明接收):<Route path="/demo/test/:name/:age" component={Test}/> 接收参数:this.props.match.params 2.search参数 路由链接(携带参数):<Link to='/demo/test?name=tom&age=18'}>详情</Link> 注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/> 接收参数:this.props.location.search 备注:获取到的search是urlencoded编码字符串,需要借助querystring解析 3.state参数 路由链接(携带参数):<Link to={{pathname:'/demo/test',state:{name:'tom',age:18}}}>详情</Link> 注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/> 接收参数:this.props.location.state 备注:刷新也可以保留住参数
|
params参数
1 2 3 4 5 6 7
|
{} <Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>
{} <Route path="/home/message/detail/:id/:title" component={Detail}/>
|
1 2 3 4
|
const {id,title} = this.props.match.params
|
search参数
1 2 3 4 5 6 7
|
{} <Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link>
{} <Route path="/home/message/detail" component={Detail}/>
|
1 2 3 4 5 6 7
|
import qs from 'querystring'
const {search} = this.props.location const {id,title} = qs.parse(search.slice(1))
|
state参数
1 2 3 4 5 6 7
|
{} <Link to={{pathname:'/home/message/detail',state:{id:msgObj.id,title:msgObj.title}}}>{msgObj.title}</Link>
{} <Route path="/home/message/detail" component={Detail}/>
|
1 2 3 4
|
const {id,title} = this.props.location.state || {}
|
路由懒加载
1 2 3 4 5 6 7 8 9 10 11
| import Loading from './Loading' const Home = lazy(()=> import('./Home') ) const About = lazy(()=> import('./About'))
<Suspense fallback={<Loading/>}> {} <Route path="/about" component={About}/> <Route path="/home" component={Home}/> </Suspense>
|
编程式路由导航
借助this.props.history对象上的API对操作路由跳转、前进、后退
-this.props.history.push()
-this.props.history.replace()
-this.props.history.goBack()
-this.props.history.goForward()
-this.props.history.go()
BrowserRouter与HashRouter的区别
1.底层原理不一样:
BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。
HashRouter使用的是URL的哈希值。
2.path表现形式不一样
BrowserRouter的路径中没有#,例如:localhost:3000/demo/test
HashRouter的路径包含#,例如:localhost:3000/#/demo/test
3.刷新后对路由state参数的影响
(1).BrowserRouter没有任何影响,因为state保存在history对象中。
(2).HashRouter刷新后会导致路由state参数的丢失!!!
4.备注:HashRouter可以用于解决一些路径错误相关的问题。
路由的严格匹配与模糊匹配
1.默认使用的是模糊匹配(简单记:【输入的路径】必须包含要【匹配的路径】,且顺序要一致)
2.开启严格匹配:<Route exact={true} path="/about" component={About}/>
3.严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由
解决多级路径刷新页面样式丢失的问题
1.public/index.html 中 引入样式时不写 ./ 写 / (常用)
2.public/index.html 中 引入样式时不写 ./ 写 %PUBLIC_URL% (常用)
3.使用HashRouter