目录
一、SPA的理解
- 单页Web应用(single page web application,SPA)。
- 整个应用只有一个完整的页面。
- 点击页面中的链接不会刷新页面,只会做页面的局部更新。
- 数据都需要通过ajax请求获取, 并在前端异步展现。
二、路由的理解
-
什么是路由
- 一个路由就是一个映射关系(key:value)
- key为路径, value可能是function或component
-
路由分类
后端路由
- 工作过程:当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据
- 注册路由: router.get(path, function(req, res))
- 理解: value是function, 用来处理客户端提交的请求。
前端路由
- 浏览器端路由,value是component,用于展示页面内容。
- 注册路由: <Route path="/test" component={Test}>
- 工作过程:当浏览器的path变为/test时, 当前路由组件就会变为Test组件
三、react-router-dom的理解
- react的一个插件库。
- 专门用来实现一个SPA应用。
- 基于react的项目基本都会用到此库。
四、 react-router-dom相关API
-
内置组件
- <BrowserRouter>
- <HashRouter>
- <Route>
- <Redirect>
- <Link>
- <NavLink>
- <Switch>
-
其他
- history对象
- match对象
- withRouter函数
五、路由基本使用
Route安装
npm i react-router -D
或
yarn add react-router-dom
Route使用
Route 有两种方式:
HashRouter
和BrowserRouter
区别 | HashRouter | BrowserRouter |
---|---|---|
底层原理 | 使用URL的哈希值 | 使用H5的history API,不兼容IE9 |
url形式 | 路径中包含# | 路径中没有# |
刷新后对state参数的影响 | 会导致state参数丢失 | 没有任何影响 |
其他 | 可以解决一些路径上的错误 |
BrowserRouter
//引入react核心库
import React from 'react'
//引入ReactDOM
import ReactDOM from 'react-dom'
//
import {BrowserRouter} from 'react-router-dom'
//引入App
import App from './App'
ReactDOM.render(
<BrowserRouter>
<App/>
</BrowserRouter>,
document.getElementById('root')
)
HashRouter
使用 HasRouter URL路径中包含#,如:http://localhost:3000/#/
//引入react核心库
import React from 'react'
//引入ReactDOM
import ReactDOM from 'react-dom'
//
import {HashRouter } from 'react-router-dom'
//引入App
import App from './App'
ReactDOM.render(
<HashRouter>
<App/>
</HashRouter>,
document.getElementById('root')
)
Link 和 NavLink
Link
- Link相当于一个a标签,当点击Link时页面会跳转到Link的to地址
<Link to="/about" ></Link>
相当于
<a href="/about"><a/>
- 使用Link必须要注册一个路由,Route注册的path地址为Link的跳转地址
<Route path="/about" component={About}/>
NavLink
NavLink
是Link
的升级版NavLink
和Link
都可以在里面设置样式- 但是只有
NavLink
可以追加样式 NavLink
还有个独特的属性activeClassName
- 谁被点击就会追加
activeClassName
里面的样式
例:
<NavLink activeClassName="RedColor" to="/about">About</NavLink>
- 如果NavLink用的比较多可以封装一个NavLink,作为一个组件使用
import React, { Component } from 'react'
import {NavLink} from 'react-router-dom'
export default class MyNavLink extends Component {
render() {
return (
<NavLink activeClassName="RedColor" {...this.props}/>
)
}
}
Switch
- 匹配到第一个路由后不再进行匹配
- 使用import {Switch} from 'react-router-dom'导入
<Switch>
<Route path="/about" component={About}/>
<Route path="/home" component={Home}/>
</Switch>
exact 属性
- exact 属性表示是否精准的匹配路径。有两个值true和false
- exact={true} 或 exact
- exact={false} 可以省略不写
-
精准匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由
不使用exact,点击home或homea都会匹配path为'/home'的路由
<Link to="/home">home</Link>
<Link to="/home/a">homea</Link>
<Route path="/home" component={Home}/>
不使用exact,点击about会匹配path为'/about'和'/about/a'的路由
<Link to="/about/a">about</Link>
<Route path="/about" component={About}/>
<Route path="/about/a" component={Abouta}/>
使用exact,点击home会匹配path为'/home'的路由,而点击homea不会匹配到路由
<Link to="/home">home</Link>
<Link to="/home/a">homea</Link>
<Route exact path="/home" component={Home}/>
Redirect使用
-
当第一次载入页面时,使用Redirect路由重定向,默认展示一个组件
-
一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由
-
使用import {Redirect} from 'react-router-dom'导入
<Switch>
<Route path="/about" component={About}/>
<Route path="/home" component={Home}/>
<Redirect to="/about"/>
</Switch>
路由嵌套
- 注册子路由时要写上父路由的path值
- 路由的匹配是按照注册路由的顺序进行的
<Link to="/home/news">News</Link>
路由组件传参
传参方式有三种:params参数、search参数、state参数
-
params参数
路由链接(携带参数):<Link to='/demo/test/tom/18'}>详情</Link>
注册路由(声明接收):<Route path="/demo/test/:name/:age" component={Test}/>
接收参数:this.props.match.params
-
search参数
路由链接(携带参数):<Link to='/demo/test?name=tom&age=18'}>详情</Link>
注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
接收参数:this.props.location.search
备注:获取到的search是urlencoded编码字符串,需要借助querystring解析
-
state参数
路由链接(携带参数):<Link to={{pathname:'/demo/test',state:{name:'tom',age:18}}}>详情</Link>
注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
接收参数:this.props.location.state
备注:刷新也可以保留住参数
Route push和replace模式
-
push
想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL
当你点击 时,这个方法会在内部调用,所以说,点击 等同于调用 router.push(…)。
-
replace
设置 replace 属性的话,当点击时,会调用 router.replace() 而不是 router.push(),于是导航后不会留下 history 记录。即使点击返回按钮也不会回到这个页面。
编程式路由导航
借助this.prosp.history对象上的AP后退I对操作路由跳转、前进、
-this.prosp.history.push()
-this.prosp.history.replace()
-this.prosp.history.goBack()
-this.prosp.history.goForward()
-this.prosp.history.go()
withRouter 函数
- withRouter 可以给普通的组件添加路由属性
- 一般用在头部,尾部,withRouter 用法是高阶组件
import React, { Component } from 'react'
import {withRouter} from 'react-router-dom'
class Header extends Component {
back = ()=>{
this.props.history.goBack()
}
forward = ()=>{
this.props.history.goForward()
}
go = ()=>{
this.props.history.go(-2)
}
render() {
console.log('Header组件收到的props是',this.props);
return (
<div className="page-header">
<h2>React Router Demo</h2>
<button onClick={this.back}>回退</button>
<button onClick={this.forward}>前进</button>
<button onClick={this.go}>go</button>
</div>
)
}
}
export default withRouter(Header)
//withRouter可以加工一般组件,让一般组件具备路由组件所特有的API
//withRouter的返回值是一个新组件