本文已参与[新人创作礼]活动,一起开启掘金创作之路
一.路由介绍
现代的前端应用大多都是 SPA(单页应用程序),也就是只有一个 HTML 页面的应用程序。因为它的用户体验更好、对服务器的压力更小,所以更受欢迎。为了有效的使用单个页面来管理原来多页面的功能,前端路由应运而生。前端路由的功能:让用户从一个视图(页面)导航到另一个视图(页面)
- 前端路由是一套映射规则,在React中,是 URL路径 与 组件 的对应关系
- 使用 React 路由简单来说就是:配置路径和组件(配对)
二.路由5.X的配置及其与6.X的区别
三.路由三大对象之-Router
两种常用 Router
HashRouter=====hash
HashRouter:使用 URL 的哈希值实现 /#/page1
#之后的部分就是hash值,它有两个特点:
- hash值的变化(地址栏中改了hash值再回车)不会重新发请求。它不是请求路径的一部分。
- hash值的变化会触发hashChange事件。
BrowserRouter====history
用 H5 的 history.pushState() API 实现
原理:监听 window 的 popstate 事件来实现的
四.基本使用步骤
1.下包
yarn add react-router-dom@5.2.1
2.导包
import { HashRouter as Router, Route, Link } from 'react-router-dom'
使用Router包裹住整个return,一个项目只有一个Router
3.使用
使用Route指定路由规则(哪个路径显示哪个组件)
import React from 'react'
import {HashRouter as Router, Route, Link} from 'react-router-dom'
import Layout from './Layout'//注意Layout为该路径暴露出的组件
const Func = () => {
return (
<Router>
<div>
logout
<Link to='/layout/first'>登录</Link>
<Route path='/layout' component={Layout}></Route>
</div></Router>)
};
export default Func
五.路由三大对象之-Route
-
作用: 决定路由匹配规则
-
格式:
<Route path="/xx/xx" component={组件}></Route>
匹配规则
名词约定:
-
path: Route组件中path属性的值
-
pathname: 指的如下格式
- link组件中to的属性值
- 地址栏中的地址
模糊匹配规则
- 只要pathname以path开头就算匹配成功
- 匹配成功就加载对应组件;
- 整个匹配过程是逐一匹配,一个匹配成功了,并不会停止匹配。
模糊匹配和精确匹配
- 默认是模糊匹配的
- 补充exact可以设置成精确匹配
六.路由三大对象之-Link
-
掌握Link和NavLink的区别;
-
能使用NavLink设置高亮效果;
import { Link, NavLink } from 'react-router-dom'
1.Link
Link组件最终会渲染成a标签,用于指定路由导航
- to属性,将来会渲染成a标签的href属性
Link组件无法展示哪个link处于选中的效果
2.NavLink
NavLink组件,一个更特殊的Link组件,可以用用于指定当前导航高亮
格式:<NavLink to="/xxx" activeClassName="active">链接</NavLink>
3.说明:
- to属性,用于指定地址,会渲染成a标签的href属性
- activeClassName: 用于指定高亮的类名,默认
active。一般不去修改。 - exact: 精确匹配,表示必须地址栏和to的属性值 精确匹配类名才生效,如果有3个写了一个就会只限制写的那个,若想都限制需要都写
- switch:将多个路由占位符包住,不管有多少个Route的路由规则匹配成功,都只会渲染第一个匹配的组件
- '/'是关键字,跟所有路径都相似,若同时跟其他路径使用的话最好配合switch和exact
说多了也没啥用,上事例
4.重定向和404
404思路:不设置path属性,将404页对应的路由放在switch内部的最后位置
重定向思路:利用from使对应路由直接跳转到to设置的路由中
<Redirect from='/' to='qq'></Redirect>//重定向
<Route component={Func}></Route>//404
建议用Switch包起来,因为404没有路径不包住的话每个页面都会显示
七.编程式导航
- 用户点击链接跳转
- 写代码跳转-编程式导航
import { useHistory,useLocation } from 'react-router-dom'
const history = useHistory()
const location=useLocation()
<li onClick={()=>history.push('/layout/first')}> first</li>
了解:history.replace和push的区别
push:向历史记录中添加一条
replace:在历史记录中用目标记录来替换当前记录
八.声明式导航
<NavLink to="/layout/second">second</NavLink>
<Link to='/layout/first'>登录</Link>
九.路由嵌套
配置嵌套路由的时候,需要对路径进行处理,必须要先匹配到父级路由,才能匹配到子路由
十.综合实例:路由显示左侧菜单
可copy
样式 src\App.css
.app .layout{
width: 100vw;
height: 100vh;
background-color: pink;
display: flex;
flex-direction: column;
}
.app .box{
display: flex;
flex:1;
}
.app .box .sideBar{
width:200px;
background-color: yellow;
}
.app .box main{
flex:1;
background-color: green;
}
.app .box .right{
background-color: rgb(7, 197, 255);
}
登录 src\views\Router\admin\Layout.js
import React from 'react'
import {
HashRouter as Router,
Route,
Link,
NavLink,
} from 'react-router-dom'
import First from './First'
import Second from './Second'
import Third from './Third'
import Forth from './Forth'
const Layout = (props) => {
return (
<Router>
<div className="layout">
<header>
<Link to="/logout">退出</Link>
</header>
<div className="box">
<div className="sideBar">
<ul>
<li onClick={()=>props.history.push('/layout/first')}>
first
</li>
<li>
<NavLink to="/layout/second">second</NavLink>
</li>
<li>
<NavLink to="/layout/third">third</NavLink>
</li>
<li>
<NavLink to={{
pathname:'/layout/forth',
state:{id:1,name:'rose'}
}}>forth</NavLink>
</li>
</ul>
</div>
<div className="right">
<Route path="/layout/first" component={First}></Route>
<Route path="/layout/second" component={Second}></Route>
<Route path="/layout/third" component={Third}></Route>
<Route path="/layout/forth" component={Forth}></Route>
</div>
</div>
</div>
</Router>
)
}
export default Layout
登出 src\views\Router\admin\Logout.js
import React from 'react'
import {HashRouter as Router, Route, Link} from 'react-router-dom'
import Layout from './Layout'
const Func = () => {
return (
<Router>
<div>
==logout
<Link to='/layout/first'>登录</Link>
<Route path='/layout' component={Layout}></Route>
</div></Router>)
};
export default Func
主页 src\App.js
import React from 'react'
import {HashRouter as Router, Route,Redirect } from 'react-router-dom'
import './App.css'
import Layout from './views/Router/admin/Layout'
import Logout from './views/Router/admin/Logout'
class Com extends React.Component {
render() {
return (
<Router>
<div className="app">
<Redirect from='/' to='/layout/first'></Redirect>
<Route path='/layout' component={Layout}></Route>
<Route path="/logout" component={Logout}></Route>
</div>
</Router>
)
}
}
export default Com
注意:占位符放在你需要跳转的位置
其他那些二级就没必要发了,随便搞个皮就好
效果图
十一.路由传参
准备工作
登录页 src\views\Router\admin\Layout.js
<li>
<NavLink to='/layout/forth'>forth</NavLink>
<Route path="/layout/forth" component={Forth}></Route>
</li>
params传参
登录页 src\views\Router\admin\Layout.js
<li>
<NavLink to='/layout/forth/123'>forth</NavLink>
</li>
<Route path="/layout/forth/:id" component={Forth}></Route>
在src\views\Router\admin\Forth.js 我们打印props可以看到传过来的参数
可使用{props.match.params.id}调用
注:传多个参数可直接使用/:id/:name即可
query传参
<li>
<NavLink to='/layout/forth?id=321'>forth</NavLink>
</li>
此时我们在src\views\Router\admin\Forth.js获取到的是"?id=321"
我们可以封装一个工具函数
let obj={}
const fn=(q)=>{
// let q=props.location.search
q=q.slice(1)
let p=q.split('&')
for( let k of p) {
let item = k.split('=')
// console.log(item);
obj[item[0]]=item[1]
}
// return obj
console.log(obj);
}
fn(props.location.search)
效果
注:传多个参数可参考?id=321&gender=男使用
隐式传参
<li>
<NavLink to={{
pathname:'/layout/forth',
state:{id:1,name:'rose'}
}}>forth</NavLink>
</li>
之前的两种都可以在网址上直接看到,这种则不会
打印props,可以找到数据的获取路径