现代的前端应用大多都是SPA(单页面应用程序),也就是只有一个HTML页面的的应用程序,因为SPA的用户体验感更好,对服务器的压力更小,随意更受欢迎,为了有效使用单页面来管理多页面的功能,前端路由应运而生
前端路由的功能:让用户从一个页面导航到另一个页面
前端路由就是一套映射规则,在react中,就是url和组件之间的映射关系
1. react-router安装及简介
-
react-router提供多个包可以单独使用
在浏览器中运行只需要安装react-router-dom,reac-router-dom依赖react-router会自动安装依赖,所以不需要再手动安装react-routernpm install react-router-dom -S
-
基本组件
在 react-router 里面,一共有 3 种基础组件,他们分别是
* 路由组件(router components) 比如 <BrowserRouter> 和 <HashRouter>
* 路由匹配组件(route matchers components) 比如 <Route> 和 <Switch>
* 导航组件(navigation components) 比如 <Link>, <NavLink>, 和 <Redirect>
2. 路由组件
对于 web 项目,react-roruter-dom 提供了 <BrowserRouter> 和 <HashRouter>两个路由组件。
BrowserRouter:浏览器的路由方式,也就是使用 HTML5 提供的 history API ( pushState , replaceState 和 popstate 事件) 来保持 UI 和 url 的同步。这种方式在react开发中是经常使用的路由方式,但是在打包后,打开会发现访问不了页面,所以需要通过配置 nginx 解决或者后台配置代理。
HashRouter:在路径前加入#号成为一个哈希值,Hash 模式的好处是,再也不会因为我们刷新而找不到我们的对应路径,但是链接上面会有 #/。在vue开发中,经常使用这种方式。
要使用路由组件,我们只需要确保它是在根组件使用,我们应该将包裹在路由组件下面:
import { BrowserRouter } from 'react-router-dom';
...
<BrowserRouter>
<App />
</BrowserRouter>
...
3. 路由匹配组件
有两种路由匹配组件:<Route> 和 <Switch>
这两个路由匹配组件通常在一起使用,在<Switch>里面包裹多个<Route>,然后它会逐步去比对每个<\Route>的path属性和浏览器当前location的pathname是否一致,如果一致则返回内容,否则返回null。
<Switch>
<Route exact path='/' component={Home} />
{/* 如果当前的URL是`/about`,即 location = { pathname: '/about' } ,那么About组件就应该被渲染,其余的Route就会被忽略 */
<Route path='/about' component={About} />
<Route path='/contact' component={Contact} />
</Switch>
模糊匹配
只会匹配 URL的开头,而不是整个 URL。简单的来说就是它不是精确匹配 ,例如 和 它永远都只能匹配到,他们开头都有’/’。
在这里我们有两种解决方法:
方法一:将此<Route path=’/’>放在
方法二:添加’exact’ 实现精确匹配:<Route exact path=’/’ component={Home} />
所以<Switch>组件只会 render 第一个匹配到的路由,像上面我们说的,如果没有设置 path,则一定会匹配,我们可以用来实现 404 的功能:
<Switch>
<Route exact path='/' component={Home} />
<Route path='/about' component={About} />
<Route path='/contact' component={Contact} />
{/* 当上面的组件都没有匹配到的时候, 404页面 就会被 render */}
<Route render={() => <div> 404页面 </div>} />
</Switch>
4. 导航组件
导航组件有<Link>, <NavLink>, 和 <Redirect>。
当我们使用<Link>的时候,在 html 页面会被渲染为一个a标签:
<Link to='/'>Home</Link>
// <a href='/'>Home</a>
是一种特殊的 ,当中的地址和浏览器地址匹配成功的时候,会添加一个 style 样式,如下:
<NavLink to='/about' activeClassName='active'>
About
</NavLink>
// 在 html 页面当中,它会被渲染为:
<a href='/about' className='active'>
About
</a>
但是想要强制跳转到某个页面,比如未登录不能进入首页,这个时候可以使用<Redirect>
<Redirect to='/login' />
5. Route动态传参
在一个路由匹配组件上设置参数,比如
<Route path="/person/:id" component={Person}></Route>
设置是以:开始然后紧跟key值,然后我们在Person组件中就可以通过获取props获取这个参数值
import React from 'react';
export default class Person extends React.Component {
constructor(props) {
super(props);
console.log(this.props.match.params.id)
}
render() {
const id = this.props.match.params.id
return (
<div>
<h2>个人中心页面</h2>
<p>个人id是:{id}</p>
</div>
)
}
}
以上为传统class组件的写法,现在可以使用hooks,可以使用useParams,代码如下:
import React from 'react';
import { useParams } from 'react-router-dom'
const Person = () => {
const { id } = useParams();
return (
<div>
<h2>个人中心页面</h2>
<p>个人id是:{id}</p>
</div>
)
}
6. react-router-dom编程式导航
-
传递字符串
this.props.history.push('/detail');
-
使用JSON对象切换页面 this.props.history.push({对象})
export default class Home extends React.Component { constructor(props) { super(props); } jumpPage = () => { this.props.history.push({ pathname: '/detail', search: "?sort=name", hash: "#the-hash", state: { id: 3 } }) } render() { return ( <div> <button onClick={this.jumpPage}>通过函数跳转</button> </div> ) } } /*接收参数的方式 *. 使用 this.props.history.location.state 来接收传递过来的参数 *. 地址栏会出现 /detail?sort=name#the-hash 内容 */
-
在可能会出现死循环的地方使用replace来跳转; 跳转到 ‘/detail’ 路径
this.props.history.replace(’/detail’); -
返回上级页面的时候使用
this.props.history.goBack();