• 04-React路由5版本(高亮, 嵌套, 参数传递... )


    React-Router-Dom(路由版本[5])

    简介

    1. React的一个插件库
    2. 用于实现SPA应用
    3. 基于React的项目基本都用

    API

    其它

    1. history对象
    2. match对象
    3. withRouter函数

    添加依赖

    yarn add react-router-dom@5
    

    使用

    BrowserRouter+Link+Route

    1. import {Link, BrowserRouter, Route} from 'react-router-dom'
    2. // 需要在最外面包裹一个路由管理器 也可以包在index.js的app组件外面
    3. <BrowserRouter>
    4. <div style={{textAlign: 'center'}}>
    5. <div>
    6. {/*定义导航连接*/}
    7. <Link to="/home">Home</Link>
    8. <br/>
    9. <Link to="/about">About</Link>
    10. </div>
    11. <div>
    12. {/*注册路由*/}
    13. <Route path="/about" component={About}/>
    14. <Route path="/home" component={Home}/>
    15. </div>
    16. </div>
    17. </BrowserRouter>

    BrowserRouter+NavLink+Route

    和Link功能一样, 但是会在点击的时候自动追加和移除一个class,那就是active, 可以通过属性activeClassName修改

    1. .active {
    2. background-color: skyblue;
    3. }

    就是一个这样的效果

    BrowserRouter+NavLink+Switch+Route

    主要说一下Switch的用法的作用

    1. import {Link, BrowserRouter, Route, NavLink, Switch} from 'react-router-dom'
    2. <Switch>
    3. <Route path="/about" component={About}/>
    4. <Route path="/home" component={Home}/>
    5. <Route path="/home" component={About}/>
    6. </Switch>

    在注册路由时可以使用Switch包裹, 如果不使用, 那么路由匹配遇到相同的, 还会继续往下匹配,并且全部展示

    不包裹VS包裹

    包裹后, 遇到第一个匹配的路由,就会展示并返回, 不往下继续匹配

    样式丢失问题解决[扩展]

    index.html

    1. 在引用样式的时候写%PUBLIC_URL%
    2. 使用绝对路径
    3. 使用HashRouter[基本不用]

    模糊匹配与精准匹配

    默认采用模糊匹配

    路由中包含传递的值,即可展示

    还是可以展示的,但是路径已经变成了/home/a/b

    使用exact={true}可以开启精准匹配

    开启精准匹配后再次访问, 就没有展示了

    BrowserRouter+NavLink+Switch+Route+Redirect

    1. import {Link, BrowserRouter, Route, NavLink, Switch, Redirect} from 'react-router-dom'
    2. import React, {Component} from 'react';
    3. import {Link, BrowserRouter, Route, NavLink, Switch, Redirect} from 'react-router-dom'
    4. import About from "./components/About";
    5. import Home from "./components/Home";
    6. import './App.css'
    7. class App extends Component {
    8. render() {
    9. return (
    10. // 需要在最外面包裹一个路由管理器 也可以包在index.js的app组件外面
    11. <BrowserRouter>
    12. <div style={{textAlign: 'center'}}>
    13. <div>
    14. {/*定义导航连接*/}
    15. <NavLink to="/home">Home</NavLink>
    16. <br/>
    17. <NavLink to="/about">About</NavLink>
    18. </div>
    19. <div>
    20. {/*注册路由*/}
    21. <Switch>
    22. <Route path="/about" component={About}/>
    23. <Route path="/home" component={Home}/>
    24. <Redirect to="/home" />
    25. </Switch>
    26. </div>
    27. </div>
    28. </BrowserRouter>
    29. );
    30. }
    31. }
    32. export default App;

    Redirect, 就是重定向的意思, 用于路由中没有匹配到路径的情况, 就会走Redirect重定向到指定路径

    输入

    默认会中定向到home

    嵌套路由使用

    1. import React, {Component} from 'react';
    2. import {NavLink, Redirect, Route, Switch} from "react-router-dom";
    3. import News from "../../pages/News";
    4. import Messages from "../../pages/Messages";
    5. class Index extends Component {
    6. render() {
    7. return (
    8. <div>
    9. <h2>this is home...</h2>
    10. <div>
    11. <h4>导航</h4>
    12. <NavLink to="/home/news">News</NavLink>
    13. <br/>
    14. <NavLink to="/home/messages">Messages</NavLink>
    15. </div>
    16. <div style={{textAlign: 'center'}}>
    17. <h4>内容</h4>
    18. <Route path="/home/news" component={News}/>
    19. <Route path="/home/messages" component={Messages}/>
    20. </div>
    21. </div>
    22. );
    23. }
    24. }
    25. export default Index;

    在Home组件中继续使用NavLink+Route注册路由, 但是需要携带前缀, 并且在外部不能开启精准模式,不然会造成匹配不到的情况,二级路由也可以使用Redirect实现默认选中

    路由组件传递参数[params]

    1. import React, {Component} from 'react';
    2. import {Link, NavLink, Route} from "react-router-dom";
    3. import Detail from "./Detail";
    4. class Index extends Component {
    5. state = {
    6. items: [
    7. {id: '1', name: 'React'},
    8. {id: '2', name: 'Vue'},
    9. {id: '3', name: 'Ts'}
    10. ]
    11. }
    12. render() {
    13. const {items} = this.state
    14. return (
    15. <div>
    16. <ul>
    17. {
    18. items.map(item => {
    19. return (
    20. <li key={item.id}>
    21. {/* 向路由组件传递params参数 */}
    22. <Link to={`/home/messages/detail/${item.id}/${item.name}`}>{item.name}</Link>
    23. </li>
    24. )
    25. })
    26. }
    27. </ul>
    28. <hr/>
    29. {/*接收params参数*/}
    30. <Route path='/home/messages/detail/:id/:title' component={Detail} />
    31. </div>
    32. );
    33. }
    34. }
    35. export default Index;
    1. import React, {Component} from 'react';
    2. const data = [
    3. {id: '1', content: 'this is React'},
    4. {id: '2', content: 'this is Vue'},
    5. {id: '3', content: 'this is Ts'}
    6. ]
    7. class Index extends Component {
    8. render() {
    9. const {id, title} = this.props.match.params
    10. const item = data.filter(x=>x.id===id)[0]
    11. return (
    12. <div>
    13. <div>id:{item.id}</div>
    14. <div>name:{title}</div>
    15. <div>content:{item.content}</div>
    16. </div>
    17. );
    18. }
    19. }
    20. export default Index;

    通过路径参数传递

    路由组件传递参数[search]

    1. {/* 向路由组件传递search参数 */}
    2. <Link to={`/home/messages/detail?id=${item.id}&title=${item.name}`}>{item.name}</Link>
    3. {/*接收search参数 不需要*/}
    4. <Route path='/home/messages/detail' component={Detail}/>
    5. import React, {Component} from 'react';
    6. const data = [
    7. {id: '1', content: 'this is React'},
    8. {id: '2', content: 'this is Vue'},
    9. {id: '3', content: 'this is Ts'}
    10. ]
    11. class Index extends Component {
    12. render() {
    13. // 接收Params参数
    14. // const {id, title} = this.props.match.params
    15. const {id,title} = this.getSearch()
    16. const item = data.filter(x=>x.id===id)[0]
    17. return (
    18. <div>
    19. <div>id:{item.id}</div>
    20. <div>name:{title}</div>
    21. <div>content:{item.content}</div>
    22. </div>
    23. );
    24. }
    25. // 获取search参数
    26. getSearch = () => {
    27. let search = this.props.location.search
    28. search = search.substring(1);
    29. let conditions = search.split("&")
    30. let obj = {}
    31. conditions.map(condition => {
    32. const kv = condition.split("=")
    33. obj[kv[0]] = kv[1]
    34. })
    35. return obj
    36. }
    37. }
    38. export default Index;

    在这里 我是自己实现了参数的解析, 也可以使用querystring的方法, 当热这个库在React18之后已经被弃用了, 本来我也想试一下的,但是发现不行

    调用直接报错

    应该是已经没有依赖了, 可以自己安装一下, 我就不安装了

    路由组件传递参数[state(和组件的state没有关系)]

    1. {/* 向路由组件传递state参数[和组件的state没有关系] */}
    2. <Link to={{pathname:'/home/messages/detail',state:{id:item.id,title:item.name}}}>{item.name}</Link>
    3. {/*接收state参数 不需要*/}
    4. <Route path='/home/messages/detail' component={Detail}/>
    5. import React, {Component} from 'react';
    6. const data = [
    7. {id: '1', content: 'this is React'},
    8. {id: '2', content: 'this is Vue'},
    9. {id: '3', content: 'this is Ts'}
    10. ]
    11. class Index extends Component {
    12. render() {
    13. // 接收Params参数
    14. // const {id, title} = this.props.match.params
    15. // 接受Search参数
    16. // const {id,title} = this.getSearch()
    17. // 接受state参数
    18. const {id, title} = this.props.location.state
    19. const item = data.filter(x=>x.id===id)[0]
    20. return (
    21. <div>
    22. <div>id:{item.id}</div>
    23. <div>name:{title}</div>
    24. <div>content:{item.content}</div>
    25. </div>
    26. );
    27. }
    28. // 获取search参数
    29. getSearch = () => {
    30. let search = this.props.location.search
    31. search = search.substring(1);
    32. let conditions = search.split("&")
    33. let obj = {}
    34. conditions.map(condition => {
    35. const kv = condition.split("=")
    36. obj[kv[0]] = kv[1]
    37. })
    38. return obj
    39. }
    40. }
    41. export default Index;

    可以直接从location.state上获取, 并且不会在地址栏上显示

    replace与push

    默认使用push,采用压栈方式存储历史记录, 可以通过back,go来完成前进或者后退

    可以修改为replace替换, 默认会替换栈顶部的历史记录, 所以不会留下痕迹, 也就不能通过back,go完成前进和后退

    修改方式为, 增加replace属性

    编程试路由导航

    1. <Link replace to={{
    2. pathname: '/home/messages/detail',
    3. state: {id: item.id, title: item.name}
    4. }}>{item.name}</Link>
    5. <button style={{marginLeft: '5px'}} onClick={event => {
    6. this.show(item.id, item.name, 'push')
    7. }}>push</button>
    8. <button style={{marginLeft: '5px'}} onClick={event => {
    9. this.show(item.id, item.name, 'replace')
    10. }}>replace</button>
    11. <Route path='/home/messages/detail/:id/:title' component={Detail}/>
    12. show = (id, title, type) => {
    13. // replace | push 路由跳转
    14. this.props.history[type](`/home/messages/detail/${id}/${title}`)
    15. }

    通过props对象上的history对象调用方法实现编程式路由跳转

    这个案例是用params参数的方式,如果是search方式就自己改一下问号, 如果是state方式, 就把对象放入参数的第二个参数,第一个是URL, 第二个就是state

    路由组件与一般组件

    1. # 直接使用定义的组件 就是一般组件 渲染时props中不会有默认路由组件的三大对象
    2. <Header />
    3. # 通过路由跳转的组件 就是路由组件 渲染时props中会携带 history location match 三大对象
    4. <Route path="/home" component={Home}/>

    如果想要在一般组件中使用路由组件的三大对象, 那么就需要withRouter函数

    withRouter

    1. import React, {Component} from 'react';
    2. import {withRouter} from "react-router-dom";
    3. class Index extends Component {
    4. render() {
    5. console.log(this)
    6. return (
    7. <div>
    8. <h2>this is Header</h2>
    9. </div>
    10. );
    11. }
    12. }
    13. export default withRouter(Index);

    这样就可以获取到三大对象了

    路由默认入参对象总结

    对象

    函数/属性

    作用

    history

    go(n)

    传入一个number数值,1代表前进一步,-1代表后退一步, 2代表前进两步

    goBack()

    后退一步

    goForward()

    前进一步

    push(uri, state)

    push方式跳转路由, 第一个参数是路由地址, 第二个是state对象

    replace(uri,state)

    replace方式跳转路由, 第一个参数是路由地址, 第二个是state对象

    location

    pathname

    路由地址

    search

    search方式传参的获取位置

    state

    state方式传参的获取位置

    match

    params

    params方式传参的获取位置

    path

    路由地址

    url

    路由地址

    BrowserRouter和HashRouter的区别

    • 底层原理不一样
      • BrowserRouter使用的是H5的History API不兼容IE9及其以下的版本
      • HashRouter使用的是URL的哈希值
    • URL的表现形式不一样
      • BrowserRouter的路径中没有#, 例如http://localhost:3000/home
      • HashRouter的路径包含#, 例如http://localhost:3000/#/home
    • 刷新后对路由state参数的影响
      • BrowserRouter没有任何影响, 应为state保存在History对象中
      • HashRouter刷新会导致路由state参数的丢失
    • 扩展: HashRouter可以用于解决一些路劲错误相关的问题
  • 相关阅读:
    关于利用talib.macd函数计算macd指标与同花顺不一致的问题
    百度地图——鹰眼轨迹服务
    【Java】数组的深浅拷贝问题(二维数组举例)(136)
    理学知识01-ppm、ppb、ppt换算
    关于node安装和nvm安装的问题
    Peter算法小课堂—归并排序
    前端使用elementui开发后台管理系统的常用功能(持续更新)
    Complete Partition Of Array
    el-upload上传组件的动态添加;el-upload动态上传文件;el-upload区分文件是哪个组件上传的。
    如何将项目部署到服务器上(全套教程)
  • 原文地址:https://blog.csdn.net/flowerStream/article/details/126493656