react-router-dom

react-router-dom

react-router-dom

–针对 web 的 react-router

–此外 react-router  还有 native(原生开发)、anywhere(任意场景)


路由基本使用

  • 明确好界面的导航区,展示区
  • 导航区的 a 标签   则替换为 Link 标签
    • name
      • 默认 push 默认,就是有历史记录的压栈模式
      • replace 就是直接替换当前的 path 没有记录也无法返回
  • 展示区使用      标签进行路由注册
  • 路由组件一般都放到 src/pages 中
  • index.js 中的最外层则包裹了一个标签。 如同 vue 中把配置的路由实例对象加入到 vue 实例中。
    •   –history 模式   >推荐  
      • BrowserRouter 使用的是 H5 的 history API,不兼容 IE9 及以下版本。
      • BrowserRouter 的路径中没有#,例如:localhost:3000/demo/test
      • 刷新页面对路由的 state 参数完全没有影响。因为 state 就是保存在 histroy 对象中。
    • ** ** –hash  锚点模式
      • HashRouter 使用的是 URL 的哈希值。
      • HashRouter 的路径包含#,例如:localhost:3000/#/demo/test
      • HashRouter 刷新后会导致路由 state 参数的丢失!!!
      • 但 HashRouter 可以用于解决一些路径错误相关的问题。

路由组件和一般组件

  • 写法不同
    • 一般组件:
    • **路由组件: **
  • 存放位置不同
    • 一般组件 :components
    • 路由组件:pages
  • 接收到的 props 不同
    • 一般组件:写组件标签时传递了什么,就能收到什么
    • 路由组件:接收到三个固定的属性
      • this.props.match.params—即可获取路由传递过来的参数。

其他标签组件

  • 替换可为选中的导航栏加上选中 active 属性。
    • 使用 activeClassName=”自定义样式” 可以自定义选中样式,不设置有默认样式
    • 但如果使用其他样式框架(bootstrap),需要 在自定义属性后 添加 !important

  • 用 switch 标签   包裹 Route 标签,path 匹配到了不会再往下执行了,提升效率(单一匹配)。path 太多才使用

  • 1.重定向。一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到 Redirect 指定的路由
  • 2.具体编码:

路由传参


1.params 参数

  • 路由链接(携带参数):<Link to=**{ **/demo/test<font style="background-color:#FFFAA5;">/tom/18</font>  ******}**>详情
    • 如果 path 中有变量   需要使用 js 的模板字符串拼接
    • 使用 {/xx/xx/${js 表达式} \*\*****}**
  • 注册路由(声明接收):<Route path=”/demo/test/:name/:age“ component={Test}/>
  • 接收参数:this.props.match.params

2.search 参数

**        –就是 query 传参的模式**

  • 路由链接(携带参数):<Link to=’/demo/test?name=tom&age=18‘}>详情5
  • 注册路由(无需声明,正常注册即可):
  • 接收参数:this.props.location.search
  • 备注:获取到的 search 是 urlencoded 编码字符串,需要借助 querystring 解析
    • urlencoded

组成格式

- **键值对**组成
- 键和值之间用 **= **:name=poloyy
- 多个键值对之间用 **& **:name=poloyy&age=19
  • 使用 querystring,react 脚手架自带的库。
    • import qs from ‘querystring’
    • :普通 json 对象转换成 urlencoded
      • qs.stringify(obj)
    • : urlencoded  转成 json 对象
      • qs.parse(str.slice(1)–去除问号

3.state 参数

  • 路由链接(携带参数):url 中不会暴露参数,且这个 state 跟组件实例中的 state 没有一点关系
  • <Link to=**{{pathname:'/demo/test',state:{name:'tom',age:18}}}**>详情</Link>
  • 注册路由(无需声明,正常注册即可):
  • 备注:就算 url 中没有参数,刷新也可以保留住参数。因为参数存在浏览器缓存中的
  • 接收参数:this.props.location.state
    • 由于第一次参数没有拿到会报错。所以牵扯到 state 的地方 都需要 加上 **’ ** **|| {} **
    • 默认给一个空对象,让控制台闭嘴。

编程式路由导航

类似 vue 的 this.$router.xxx

**但 react 的需用借助 路由组件的 props 中的 history 进行路由操纵     **

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

  • this.prosp.history.push(path,参数)
  • -this.prosp.history.replace(path,参数)
  • -this.prosp.history.goBack()
  • -this.prosp.history.goForward()
  • -this.prosp.history.go()

路由懒加载

  • 就是按需引入   组件,当点击才加载,跟 vue 配置相似,但需要借助 react 中的 lazy 函数

  • 但需要 Suspense 组件   包裹 Route,必须要有 fallback 属性,其可以绑定一个路由跳转时的保留组件(Loading…)。此组件就普通引入即可。

扩展

1. 普通组件转为路由组件

使用 react-router-dom 提供的 **withRouter****函数**

–导出 withRouter(组件) ,该组件就会变为路由组件,就可以使用路由组件的 porps 中的各个属性,操作路由。

2.中 componet 与 render/children 区别

component={组件}。直接挂载 router 底下,就是可以直接使用 路由 props。componet 使用箭头传递 props 会造成 渲染的组件重复 挂载和卸载。所以传递 props 时,使用 render 或 children。**组件用箭头函数就用,render/children**

其背后的原理在于,react 在比较组件状态以便决定如何更新 dom 节点时,首先要比较组件的 type 和 key。在使用<Route component={() => ()}/>时,由于调用了React.createElement,组件的 type 不是routeTest这个类,而是一个匿名函数。App 组件每次 render 时都生成一个新的匿名函数,导致生成的组件的 type 总是不相同,所以会产生重复的 unmounting 和 mounting。

**render**<font style="color:#3665EE;">={()=>{组件}}</font>,返回一个处理过的组件,需要主动传递 路由 props。他是允许内联渲染和包装

3. 解决多级路径跳转后刷新页面,样式丢失的问题。

->>由于路径找不到,就默认使用 index.html。因为它就是个兜底的

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

4. 路由的严格匹配与模糊匹配

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

5.嵌套路由

  • 1.注册子路由时要写上父路由的 path 值
  •  2.路由的匹配是按照注册路由的顺序进行的
    • 因为路由是模糊匹配,从最外层开始匹配,要把/home 注册起了(home 挂载上了),才能注册到/home/xxx

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!