第5章:React路由
5.1. 相关理解
5.1.1. SPA的理解
- 单页Web应用(single page web application,SPA)。
- 整个应用只有一个完整的页面。
- 点击页面中的链接不会刷新页面,只会做页面的局部更新。
- 数据都需要通过ajax请求获取, 并在前端异步展现。
5.1.2. 路由的理解
- 什么是路由?
- 一个路由就是一个映射关系(key:value)
- key为路径, value可能是function或component
- 路由分类
- 后端路由:
- 理解: value是function, 用来处理客户端提交的请求。
- 注册路由: router.get(path, function(req, res))
- 工作过程:当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据
- 前端路由:
- 浏览器端路由,value是component,用于展示页面内容。
- 注册路由:
- 工作过程:当浏览器的path变为/test时, 当前路由组件就会变为Test组件
- 后端路由:
5.1.3. react-router-dom的理解
- react的一个插件库。
- 专门用来实现一个SPA应用。
- 基于react的项目基本都会用到此库。
5.2. react-router-dom相关API
5.2.1. 内置组件
<BrowserRouter>
<HashRouter>
解决多级路径刷新页面样式丢失的问题- public/index.html中引入样式时不写./写/ (常用)。
- public/index.html中引入样式时不写./写%PUBLIC_URL% (常用)。
- 使用HashRouter 。
<Route>
<Redirect>
- 一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由。
- 具体编码:
<Switch> <Route path="/about" component=[About)/> <Route path="/home" component=[Home)/> <Redirect to="/about"/> </Switch>
<Link>
<NavLink>
- NavLink可以实现路由链接的高亮,通过activeClassName指定样式名
<NavLink activeClassName="show" to="/about">About</NavLink>
。 - 标签体内容是一个特殊的标签属性。
- 通过this.props.children可以获取标签体内容 。
封装一个MyNavLink
<MyNavLink to="/about" children="About"></MyNavLink>
import React, { Children, Component } from 'react'; import {NavLink} from 'react-router-dom' export default class MyNavLink extends Component { render() { return ( <div> <NavLink activeClassName="active" className="list-group-item" {...this.props}/> </div> ); } }
- NavLink可以实现路由链接的高亮,通过activeClassName指定样式名
<Switch>
- 通常情况下, path和component是一一对应的关系。
- Switch可以提高路出匹配效率(单一匹配)。
5.2.2. 其它
- history对象
- match对象
- withRouter函数
5.3. 基本路由使用
5.3.1. 基本使用
- 明确好界面中的导航区、展示区
- 导航区的a标签改为Link标签
<Link to="/xxxxx">Demo</Link>
- 展示区写Route标签进行路径的匹配
<Route path='/xxxx' component=[Demo)/>
<App>
的最外侧包裹了一个<BrowserRouter>
或<HashRouter>
ReactDOM.render( <BrowserRouter> <App /> </BrowserRouter>, document.getElementById('root') );
5.3.2. 路由组件与一般组件
- 写法不同:
- 一般组件:
<Demo/>
- 路由组件:
<Route path="/demo" component=[Demoy/>
- 一般组件:
- 存放位置不同:
- 一般组件: components
- 路由组件: pages
- 接收到的props不同:
- 一般组件:写组件标签时传递了什么,就能收到什么
- 路由组件:接收到三个固定的属性
- history:
- go: f go(n)
- goBack: f goBack()
- goForward: f goForward()
- push: f push(path, state)
- replace: f replace(path, state)
- location:
- pathname: “/about”
- search: “”
- state: undefined
- match:
- params:{}
- path: “/about”
- url: “/about”
- history:
5.3.3. 路由的严格匹配与模糊匹配
- 默认使用的是模糊匹配(简单记: 【输入的路径】必须包含要【匹配的路径】,且顺序要一致)。
- 开启严格匹配:
<Route exact=(true) path="/about" component=[About]/>
。 - 严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由。
5.3.4. 准备
- 下载react-router-dom: npm install --save react-router-dom
- 引入bootstrap.css:
<link rel="stylesheet" href="/css/bootstrap.css">
5.4. 嵌套路由(多级路由)使用
- 注册子路由时要写上父路由的path值
- 路由的匹配是按照注册路由的顺序进行的
<div>
<Route path="/home/news" component={News} />
<Route path="/home/message" component={Message} />
<Redirect to="/home/news"/>
</div>
5.5. 向路由组件传递参数数据
-
params参数
- 路由链接(携带参数):
<Link to='/demo/test/tom/18'>详情</Link>
- 注册路由(声明接收):
<Route path="/demo/test/:name/:age" component={Test}/>
- 接收参数:
const {id,title} = this.props.match.params
- 路由链接(携带参数):
-
search参数
- 路由链接(携带参数):
<Link to='/demo/test?name=tom&age=18'>详情</Link>
- 注册路由(无需声明,正常注册即可):
<Route path="/demo/test" component={Test}/>
- 接收参数:
const {search} = this. props.location
备注:获取到的search是urlencoded编码字符串,需要借助querystring解析
- 路由链接(携带参数):
-
state参数
- 路由链接(携带参数):
<Link to={{path: '/demo/test', state:{name: 'tom', age:18}}}>详情</Link>
- 注册路由(无需声明,正常注册即可):
<Route path="/demo/test" component={Test}/>
- 接收参数: this.props.location.state
备注:刷新也可以保留住参数
- 路由链接(携带参数):
5.6. withRouter
可以加工一般组件,让一般组件具备路由组件所特有的API,返回值是一个新组件。
class Header extends Component {
...
}
export default withRouter(Header)
5.7. BrowserRouter与HashRouter的区别
- 底层原理不一样:
- BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。
- HashRouter使用的是URL的哈希值。
- url表现形式不一样:
- BrowserRouter的路径中没#,例如: localhost:3000/demo/test
- HashRouter路径包含#,例如: localhost:3000/#/demo/test
- 刷新后对路由state参数的影响
- BrowserRouter没有任何影响,因为state保存在history对象中。
- HashRouter刷新后会导致路由state参数的丢失。
- 备注: HashRouter可以用于解决一些路径错误相关的问题。