文章目录

  • 路由组件
    • 1、HashRouter和BrowserRouter
    • 2、Route
    • 3、Router
    • 4、Link和NavLink
    • 5、Redirect
    • 6、Switch
    • 7、withRouter
  • 嵌套路由
  • 向路由组件传递参数
  • 路由跳转的两种模式
  • 编程式路由导航
  • Router Hooks

路由组件

路由组件与一般组件区别:

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”

1、HashRouter和BrowserRouter

其实就是路由的hash和history两种模式,并且这两个组件是路由的容器,必须在最外层

 // hash模式
ReactDOM.render(<HashRouter><Route path="/" component={Home}/>
</HashRouter>
)// history模式
ReactDOM.render(<BrowserRouter><Route path="/" component={Home} /></BrowserRouter>
)

区别:

  • 底层原理不一样

    • BrowserRouter使用的是H5的history API,不兼容IE9及以下版本
    • HashRouter使用的是URL的哈希值
  • path表现形式不一样
    • BrowserRouter的路径中没有#,例如:localhost:3000/demo/test
    • HashRouter的路径包含#,例如:localhost:3000/#/demo/test
  • 刷新后对路由state参数的影响
    • BrowserRouter没有任何影响,因为state 保存在history对象中
    • HashRouter刷新后会导致路由state 参数的丢失
  • 备注:HashRouter可以用于解决一些路径错误相关的问题

2、Route

路由的一个原材料,它是控制路径对应显示的组件

Route的参数:

  • path:跳转的路径
  • component: 对应路径显示的组件
  • render:可以自己写render函数返回具体的dom,而不需要去设置component
  • location: 传递route对象,和当前的route对象对比,如果匹配则跳转
  • exact: 匹配规则,true的时候则精确匹配

3、Router

低级路由,适用于任何路由组件,主要和redux深度集成,使用必须配合history对象,使用Router路由的目的是和状态管理库如redux中的history同步对接

<Router history={history}>...
</Router>

4、Link和NavLink

两者都是跳转路由,NavLink的参数更多些

Link:

  • to: 有两种写法,表示跳转到哪个路由
  • 字符串写法: <Link to="/a" />
  • 对象写法: <Link to={{ pathname: '/courses', search: '?sort=name', hash: '#the-hash', state: { fromDashboard: true } }}/>
  • replace:就是将push改成replace
  • innerRef:访问Link标签的dom

NavLink:

  • Link的所有参数

  • activeClassName: 路由激活的时候设置的类名 实现路由链接的高亮

  • activeStyle :路由激活设置的样式

  • exact: 参考Route,符合这个条件才会激活active类

  • strict: 参考Route,符合这个条件才会激活active类

  • isActive: 接收一个回调函数,active状态变化的时候回触发,返回false则中断跳转

    const oddEvent = (match, location) => {console.log(match,location)if (!match) {return false}console.log(match.id)return true
    }<NavLink isActive={oddEvent} to="/a/123">组件一</NavLink>
    
  • location: 接收一个location对象,当url满足这个对象的条件才会跳转

    <NavLink to="/a/123" location={{ key:"mb5wu3", pathname:"/a/123" }}/>
    

NavLink的使用:

在之前的效果展示中,Link组件不会进行高亮显示,因此改成NavLink用法

App.js文件修改的代码:

{/* 在React中靠路由链接实现切换组件 */}
<NavLink activeClassName="add" className="list-group-item" to="/home">Home</NavLink>
<NavLink activeClassName="add" className="list-group-item" to="/about">About</NavLink>//这里用 activeClassName="add" 来控制按钮高亮的颜色显示

index.html 文件修改后的代码:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><link rel="stylesheet" href="./css/bootstrap.css"><style>.add{background-color: rgb(209,137,4) !important; // 因为 bootstrap 的权重比较高,所以要用!importantcolor:white !important;}</style>
</head>
<body><div id="root"></div>
</body>
</html>

NavLink的封装:

因为在 App.js 文件中写 NavLink 太长了, 所以在这里把 NavLink 单独提出来写 MyNavLink 一个组件, 使用时调用它,可以使代码更加简洁

MyNavLink组件代码:

import React, { Component } from 'react'
import {NavLink} from 'react-router-dom'export default class MyNavLink extends Component {render() {return (<NavLink activeClassName="add" className="list-group-item" {...this.props} />)}
}

App.js修改后的代码:

{/* 在React中靠路由链接实现切换组件 */}
<MyNavLink to="/home">Home</MyNavLink>
<MyNavLink to="/about">About</MyNavLink>

进行封装的知识点:

  • 标签体内容是一个特殊的标签属性children
  • 通过this.props.children可以获取标签体内容

问题:

1、解决多级路径刷新页面样式丢失

如果匹配的路径不对, 就会引发css样式的丢失问题

默认执行index.html文件

App.js代码修改:

{/* 在React中靠路由链接实现切换组件 */}
<MyNavLink to="/aaa/home">Home</MyNavLink>
<MyNavLink to="/aaa/about">About</MyNavLink>{/* 注册路由 路由组件写法 */}
<Switch><Route path="/aaa/home" component={Home}/><Route path="/aaa/about" component={About}/>
</Switch>

效果:

解决方法:

  • public/index.html 中 引入样式时不写 ./ 写 / (常用)
  • public/index.html 中 引入样式时不写 ./ 写 %PUBLIC_URL% (常用)
  • 使用HashRouter

2、路由的严格匹配与模糊匹配

  • 1.默认使用的是模糊匹配(简单记:【输入的路径】必须包含要【匹配的路径】,且顺序要一致)
  • 2.开启严格匹配:<Route exact={true} path="/about" component={About}/>
  • 3.严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由

App.js代码修改:

{/* 在React中靠路由链接实现切换组件 */}
<MyNavLink to="/home">Home</MyNavLink>
<MyNavLink to="/aaa/about">About</MyNavLink>{/* 注册路由 路由组件写法 */}
<Switch><Route exact path="/home" component={Home}/><Route exact path="/about" component={About}/>
</Switch>

效果:

5、Redirect

页面重定向:一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由

<Switch><Route path="/about" component={About}/><Route path="/home" component={Home}/><Redirect to="/about"/>
</Switch>

用法:

// 基本的重定向
<Redirect to="/somewhere/else" />// 对象形式
<Redirectto={{pathname: "/login",search: "?utm=your+face",state: { referrer: currentLocation }}}
/>// 采用push生成新的记录
<Redirect push to="/somewhere/else" />// 配合Switch组件使用,form表示重定向之前的路径,如果匹配则重定向,不匹配则不重定向
<Switch><Redirect from='/old-path' to='/new-path'/><Route path='/new-path' component={Place}/>
</Switch>

6、Switch

路由切换,只会匹配第一个路由,可以想象成tab栏。Switch内部只能包含Route、Redirect和Router。

通常情况下,path和component是一一对应的关系。Switch可以提高路由匹配效率(单一匹配)。

<Switch><Route exact path="/" component={Home}/><Route path="/about" component={About}/><Route path="/:user" component={User}/><Route component={NoMatch}/>
</Switch>

7、withRouter

当一个非路由组件也想访问到当前路由的match、location、history对象,那么withRouter将是一个非常好的选择,可以理解为将一个组件包裹成路由组件

  • withRouter可以加工一般组件, 让一般组件具备路由组件所特有的API
  • withRouter的返回值是一个新组件
import { withRouter } from 'react-router-dom'
const MyComponent = (props) => {const { match, location, history } = this.propsreturn (<div>{props.location.pathname}</div>)
}
const FirstTest = withRouter(MyComponent);

示例:

效果:

Header 组件代码:

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()}/// gogo = () => {this.props.history.go(2)}render() {// console.log('一般组件',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)

嵌套路由

1.注册子路由时要写上父路由的path值

2.路由的匹配是按照注册路由的顺序进行的

News 组件代码:

import React, { Component } from 'react'export default class News extends Component {render() {return (<ul><li>news001</li><li>news002</li><li>news003</li></ul>)}
}

Message 组件代码:

import React, { Component } from 'react'export default class Message extends Component {render() {return (<div><ul><li><a href="/message1">message001</a>&nbsp;&nbsp;</li><li><a href="/message2">message002</a>&nbsp;&nbsp;</li><li><a href="/message/3">message003</a>&nbsp;&nbsp;</li></ul></div>)}
}

Home组件代码:

import React, { Component } from 'react'
import MyNavLink from '../../components/MyNavLink'
import { Route,Switch } from 'react-router-dom'
import News from './News'
import Message from './Message'export default class Home extends Component {render() {console.log('路由组件', this.props)return (<div><h3>我是Home的内容</h3><div><ul class="nav nav-tabs"><li>{/* 注册子路由时要写上父路由的path值 */}<MyNavLink to="/home/news">News</MyNavLink></li><li><MyNavLink to="/home/message">Message</MyNavLink></li></ul>{/* 注册路由 */}<Switch>{/* 注册子路由时要写上父路由的path值 */}<Route path="/home/news" component={News}/><Route path="/home/message" component={Message}/></Switch></div></div>)}
}

向路由组件传递参数


  • 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
    • 备注:刷新也可以保留住参数

示例:

Message 组件代码:

import React, { Component } from 'react'
import {Link, Route} from 'react-router-dom'
import Detail from './Detail'export default class Message extends Component {state = {messageArr:[{id:'01',title:'消息1'},{id:'02',title:'消息2'},{id:'03',title:'消息3'},]}render() {const { messageArr } = this.state;return (<div><ul>{messageArr.map((msgObj)=>{return (<li key={msgObj.id}>{/* 1、向路由组件传递params参数 */}{/* <Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link> */}{/* 2、向路由组件传递search参数 */}{/* <Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link> */}{/* 3、向路由组件传递state参数 */}<Link to={{pathname:"/home/message/detail",state:{id:msgObj.id,title:msgObj.title}>{msgObj.title}</Link></li>)})}</ul><hr />{/* 1、声明接收params参数 */}{/* <Route path="/home/message/detail/:id/:title" component={Detail}/> */}{/* 2、params参数无需声明接收, 正常注册即可 */}{/* <Route path="/home/message/detail" component={Detail}/> */}{/* 3、state参数无需声明接收, 正常注册即可 */}<Route path="/home/message/detail" component={Detail}/></div>)}
}

Detail 组件代码:

 import React, { Component } from 'react'
// import qs from 'querystring'const DetailData = [{id:'01',content:'你好,中国'},{id:'02',content:'你好,世界'},{id:'03',content:'你好,我'}
]export default class Detail extends Component {render() {// 1、接收params参数// const {id,title} = this.props.match.params// 2、接收search参数// const {search} = this.props.location// const {id,title} = qs.parse(search.slice(1))// 3、接收state参数const {id,title} = this.props.location.stateconst findResult = DetailData.find((datailObj)=>{return datailObj.id === id})return (<ul><li>id:{id}</li><li>title:{title}</li><li>context:{findResult.content}</li></ul>)}
}

路由跳转的两种模式

push与replace

默认为push,要使用replace时,在标签上加replace就行

<Link replace to={{pathname:"/home/message/detail",state:{id:msgObj.id,title:msgObj.title}>{msgObj.title}
</Link>

编程式路由导航

借助this.prosp.history对象上的API对操作路由跳转、前进、后退

  • this.prosp.history.push()
  • this.prosp.history.replace()
  • this.prosp.history.goBack()
  • this.prosp.history.goForward()
  • this.prosp.history.go()

效果:

import React, { Component } from 'react'
import {Link, Route, repalce} from 'react-router-dom'
import Detail from './Detail'export default class Message extends Component {state = {messageArr:[{id:'01',title:'消息1'},{id:'02',title:'消息2'},{id:'03',title:'消息3'},]}// push查看pushShow = (id,title) => {//push跳转+携带params参数// this.props.history.push(`/home/message/detail/${id}/${title}`)// push 跳转+携带search参数// this.props.history.push(`/home/message/detail?id=${id}&title=${title}`)// push 跳转+携带state参数this.props.history.push(`/home/message/detail`,{id,title})}// replace 查看replaceShow = (id,title) => {// replace跳转+携带params参数// this.props.history.replace(`/home/message/detail/${id}/${title}`)// replace跳转+携带search参数// this.props.history.replace(`/home/message/detail?id=${id}&title=${title}`)// push 跳转+携带state参数this.props.history.replace(`/home/message/detail`,{id,title})}back = () => {this.props.history.goBack()}forward = () => {this.props.history.goForward()}go = () => {this.props.history.go(2)}render() {const { messageArr } = this.state;return (<div><ul>{messageArr.map((msgObj)=>{return (<li key={msgObj.id}>{/* 向路由组件传递params参数 */}{/* <Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link> */}{/* 向路由组件传递search参数 */}{/* <Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link> */}{/* 向路由组件传递state参数 */}<Link to={{pathname:"/home/message/detail",state:{id:msgObj.id,title:msgObj.title}>{msgObj.title}</Link></li><button onClick={()=> this.pushShow(msgObj.id,msgObj.title)}>push查看</button><button onClick={()=> this.replaceShow(msgObj.id,msgObj.title)}>repalce查看</button>)})}</ul><hr />{/* 声明接收params参数 */}{/* <Route path="/home/message/detail/:id/:title" component={Detail}/> */}{/* params参数无需声明接收, 正常注册即可 */}{/* <Route path="/home/message/detail" component={Detail}/> */}{/* state参数无需声明接收, 正常注册即可 */}<Route path="/home/message/detail" component={Detail}/><button onClick={this.back}>回退</button><button onClick={this.forward}>前进</button><button onClick={this.go}>go</button></div>)}
}

Router Hooks

在Router5.x中新增加了Router Hooks用于在函数组件中获取路由信息。使用规则和React的其他Hooks一致

(1)useHistory:返回history对象
(2)useLocation:返回location对象
(3)useRouteMatch:返回match对象
(4)useParams:返回match对象中的params,也就是path传递的参数

import React from 'react';
import { useHistory } from 'react-router-dom';function backBtn(props) {let history = useHistory;return <button onClick={ ()=> {history.goBack();}>返回上一页</button>
}

React 路由组件 详解相关推荐

  1. React 路由react-router-dom详解

    React 路由react-router-dom详解 ( 路由嵌套 + 路由传参 + 路由权限 + 路由优化 按需导入 + 404页面 ) 前面我们先了解一下 路由是什么? 路由分类有哪些?内置API ...

  2. 一文带你搞懂React路由(详解版)

    文章目录 React 路由

  3. React路由使用详解

    安装路由 打开cmd 在项目文件夹安装:npm i react-router-dom@5.0 -S(指定5.0版本) 导入路由的相关组件 在app.js中添加路由,导入 import {HashRou ...

  4. js路由在php上面使用,React中路由使用详解

    这次给大家带来React中路由使用详解,React中路由使用的注意事项有哪些,下面就是实战案例,一起来看一下. 路由 通过 URL 映射到对应的功能实现,React 的路由使用要先引入 react-r ...

  5. 25、react 中使用路由 router 详解

    react 中使用路由 router 详解 今天开始最新的一个模块,也是 react 开发中最重要的一部分,就是路由. SPA 理解 我们使用原生的 HTML + CSS + JavaScript 开 ...

  6. Streamsets组件详解

    Streamsets优化详解 一.Origin类组件详解 二.Processor类组件详解 三.Destination类组件详解 四.Executor类组件使用详解 一.Origin类组件详解 Ama ...

  7. 视频教程-React Hooks 案例详解(React 进阶必备)-其他

    React Hooks 案例详解(React 进阶必备) Leo 1978年8月生,河北石家庄人. 曾任职中软股份. 计算科学导师: 刘坤起博士. 开发的<电商分销系统>获得淘宝Top10 ...

  8. Android笔记——四大组件详解与总结

    android四大组件分别为activity.service.content provider.broadcast receiver. -------------------------------- ...

  9. ReactNative ViewPageAndroid组件详解

    源码传送门 在我们开发Android的时候,ViewPage这个控件的使用频率还是很高的,最简单的就是制作引导页,应用程序的主界面等,在ReactNative开发中实现该功能的组件是ViewPageA ...

最新文章

  1. js传入参数为字符串问题
  2. Spring boot配置文件值注入
  3. 4个足球队打小组单循环
  4. 江夏学院计算机,福建江夏学院计算机作业.doc
  5. python某行某列读取数据_使用scrpython从某行的第一列提取数据
  6. 鸡蛋的硬度(信息学奥赛一本通-T1300)
  7. 如何手动实现C语言中的字符串操作
  8. Android 8.0(30)--- 应用快捷方式(ShortcutManager)的使用
  9. linux box 信息发布,使用Instantbox快速搭建一个开箱即用的Web端临时Linux系统
  10. 获取指定存储过程的参数定义
  11. 支持了Unicode及各国字符集编码识别]改善IDA6.8对中文等非英语国家的ANSI字符串显示支持不佳的问题...
  12. ImageView之android:tint= 属性方法作用详解
  13. Luogu2257 YY的GCD
  14. nod32 激活码 地址 NOD 32
  15. 基于Jsoup爬虫Demo
  16. LINGO使用教程(一)
  17. DC中保存ddc格式文件(亲测有效!)save the unmapped design in ddc format
  18. Hibernate源码解析
  19. session set()用法php,PHP 使用 session_set_save_handler()
  20. 聚合资金托管+支付 联动优势推出房产行业线上产品“海金居”

热门文章

  1. 首席新媒体运营商学院创始人黎想:小红书推广运营策略玩法
  2. gitlab-cicd问题总结
  3. 语音模块的开发(LU-ASR01智能语音控制模块)
  4. python编程求平均值_Python编程求平均值的两种方法是?
  5. 金融壹账通获评金保奖“保险科技最佳服务提供商”科技赋能传统保险行业
  6. 手机浏览器访问PC网站自动跳转
  7. python opencv cv2.rectangle 参数含义
  8. 复杂事件处理 java_复杂事件处理引擎—Esper入门
  9. Android自定义view仿QQ的Tab按钮动效
  10. 优化企业银行账户服务器,农行多措并举优化企业账户服务