Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 500|回复: 0

react路由解决方案

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-5-15 17:41:28 | 显示全部楼层 |阅读模式

    react-router:是react router的核心库

    react-router-dom:是网页路由的解决方案,依赖于react-router

    react-router-native:是react-native解决移动端路由的解决方案,依赖于react-router

    下面讲述的是react-router-dom的使用

    这里用的react-router版本是5.x

    react-router5.x版本和react-router3.x使用上有很大不同

    1安装路由模块

    npm i –S react-router-dom

    2路由的定义

    App.jsx

    image

    这里定义了4个页面

    <Router>定义一个路由实例,相当于一个路由容器

    <Switch>标签让路由只能匹配单个<Route>,不具包含性的匹配多个路由

    5.x的路由具有包含性和3.x的路由完全不同

    exact属性让route进行严格匹配,只有路径完全一致才会匹配成功,默认值true,可以省略不写

    eq:

    image

          在网页中匹配根路径’/’,路由匹配会按从上到下的顺序进行匹配,如果没有<Swith>标签,就会成功匹配’/’,’/about’,’/inbox’,’/coder’所有的<Route>标签,从而展示其相关的组件。

    添加<Swith>标签后,路由只能匹配单个<Route>标签,因此这里只会匹配到path=’/’的<Route>标签

    但如果在网页中匹配’/about’,这时还是会匹配到path=’/’的路由,因此需要给path=’/’的<Route>标签添加exact属性让其进行严格匹配,只有路径完全等于’/’时才会成功匹配,添加exact属性后路由就不会匹配到path=’/‘的路由上,而是匹配到path=’about’的路由

    3.将路由渲染到页面

    index.js

    image

    下面叙述相关的详细的组件

    目录结构:

    image

    Dashboard.jsx  网页根组件

    image

    这里有个公共组件Header

    Header.jsx

    image

    <Link>标签用来进行路由跳转,默认会被渲染成a标签

    About.jsx

    image

    Inbox.jsx

    image

    这里面嵌套了两个子路由,对应的组件分别是MessageLinkComponent和Message

    其中一个是动态路由,以id值作为动态路径

    获取父级路由的路径path:this.props.match.path,这里获取到的path是 ‘/inbox’

    与this.props.match.url比较:

    this.props.match.path获取的是纯路径,即定义好的路径  ‘/index/:id’

    this.props.match.url获取的是资源的路径地址  ‘/index/123’

    子路由组件:MessageLinkComponent.jsx

    image

    实现子路由的跳转,并把id值当成动态路径传出

    子路由组件:Message.jsx

    image

    子路由跳转的内容显示

    id值的获取:this.props.match.params.id

    Coder.jsx

    image

    定义了一个子路由,其对应的组件是CoderContent

    并且定义了子路由跳转的Link,实现子路由跳转,将相关数据以键值对存放于路径中并传递出去

    CoderContent.jsx

    image

    通过get传值传递来的键值对用node的url模块进行解析,解析出一个以json对象保存的query对象,并将其展示在页面上

    url.parse(this.props.location.search,true).query

    路由模块的抽离

    将路由的定义抽离成一个配置文件routesConfig.js

    routesConfig.js

    image

    相关页面也需要改写

    App.jsx

    image

    这里用三元表达式代替了if-else语句的嵌套

    注意:子路由的嵌套要将component属性改写成一个render函数,这样才能将children子路由对象传递给props参数

    image

    render函数是一个带props参数的箭头函数,结果返回一个react组件实例对象(jsx对象)

    并把children子路由挂载在实例对象的children属性上,相当于覆盖了props.children属性。

     

    从这里可以看出<Route>标签的作用仅仅只是充当了一个中间组件,最后还是需要通过render

    函数来渲染相关的即将展示的组件,并通过props参数把挂在<Route>标签上的属性传给组件实例

    例如:<Route>上的path属性最终会以this.props.match.path的形式在react组件实例中获取到

     

    Inbox.jsx

    image

    Coder.jsx

    image

    image

    js实现路由跳转

    网上有很多种方法实现,这里使用比较简单的两种方法

    1.官方推荐的组件内路由跳转

    官方推荐使用高级路由组件withRouter来包裹需要用到跳转的组件。

    这里对组件Header.jsx进行修改

    image

    被withRouter包裹的Header会给props注册一个history对象,这个history对象正是整个路由默认使用的history对象(创建BrowserRouter组件后会有一个默认的history,但不会直接暴露出来给你使用)

    history对象内容:

    image

    可以通过event.target获取dom对象,进而通过js操作dom获取元素属性to的值,即获取跳转路径,并通过this.props.push()来进行跳转

    eq: this.props.history.push(e.target.getAttribute('to'))

    也可以通过event.target.dataset.to来获取路径值,不过进行跳转的标签上要有定义data-to属性来保存路径

    eq: this.props.history.push(e.target.dataset.to)

    2.自己创建一个history对象实例来控制跳转 (比较自由)

    创建history模块

    image

    history.js

    image

    这里用了react的history库来创建,并将实例导出。

    注意将history对象引入到Router组件中,让整个路由实例使用我们创建出来的history对象,否则无法生效

    App.jsx

    image

    image

    导入后发出警告:

    image

    原来BrowserRouter忽略了history属性,因此通过BrowserRouter创建的路由也都不用手动导入history。

    为了能使用自定义的history,只好不使用提供好的BrowserRouter组件来创建路由,而是用最原始的Router组件来创建路由实例。

    image===》

    image

    然后只需要在想要使用跳转的组件中导入我们创建好的history实例,并操作history对象就能实现跳转了

    eq:

    import history from ‘modules/history’

    history.push(e.target.getAttribute('to'))

    以Header.jsx为例:

    image

    实际上这里的this.props.history和导入的history已经是同一个对象了

    实验:

    console.log(history==this.props.history) //true

    推导可以知道withRouter组件给Header注册的this.props.history属性,来自于App.jsx中导入的history => <Router history={history}> ,并且通过withRouter传递给其他组件

    补充

    由于Route组件进行的条件判断太过繁杂,于是将Switch组件和Route组件组合封装成一个Routes组件,避免页面数量多时,总要重复写这段判断代码

    Routes.js

    image

    由于对Route组件外部包裹了Routes这样一个组件,导致某些组件在调用Routes时,没有把上一层的Route组件的属性传递下去,Route组件其实就是个中间组件并且包裹了个普通组件,并把Route上的属性传递给普通组件。

    正常:Route.props –> Component.props

    嵌套后: Route.props –> Component.props –>Route2.props –> Component2.props

    Component.props –>Route2.props 这个阶段会用到 Component.props的部分值

    包裹Routes后:Routes.props –> Route.props  –> Component.props 

    因此进行路由嵌套后是这个样:

    Routes.props –> Route.props  –> Component.props  -> Routes2.props –> Route2.props  –> Component2.props

    这里得解决:Component.props  -> Routes2.props 这个阶段的传值,Routes2作用其实就是承接Component中的props,目的是为了能让Route2能正常工作

    于是得进行手动传值:<Routes {...this.props}></Routes>

    并且在Routes组件中增加了判断,判断接下来进行渲染的config用的是routesConfig还是由组件传递下来的children

    this.props.children?(this.config=this.props.children):(this.config=routesConfig)

    修改后的App.jsx变得极为简单:

    image

    Inbox.jsx也一样

    image

    同理作用于Coder.jsx

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-1-23 15:09 , Processed in 0.063875 second(s), 27 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表