• React路由组件传参的三种方式——params、search、state


    今天来学习一下向路由组件传递参数的三种方式。
    感兴趣的伙伴可以仔细看看~

    在这里插入图片描述

    🔥向路由组件传递params参数

    当点击消息1这个导航链接时,展示下方对应的Detail路由组件,并向这个组件传递params参数(ID,TITLE,CONTENT)信息。

    在这里插入图片描述

    向路由组件传递params参数:在路径后面跟上想要传递的值

    {
      messageArr.map((msgObj) => {
        return (
          <li key={msgObj.id}>
    			 <Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>
    			 {msgObj.title}</Link>
          </li>
        )
     })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    注册路由时,声明接收params参数

    <Route path="/home/message/detail/:id/:title" component={Detail} />
    
    • 1

    这样id,title参数就传递给了Detail组件,Detail组件可以通过this.props.match.params拿到参数。

    // 接收params参数
    const { id, title } = this.props.match.params
    
    • 1
    • 2

    在这里插入图片描述

    Message->index.jsx:

    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}>
                      {/* 向路由组件传递params参数 */}
                      <Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>
                      {msgObj.title}</Link>
                    </li>
                  )
                })
              }
            </ul>
            <hr />
            {/* 注册路由 */}
            {/* 声明接收params参数 */}
            <Route path="/home/message/detail/:id/:title" component={Detail} />
          </div>
        )
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    Detail->index.jsx:

    import React, { Component } from 'react'
    
    const DetailData = [
      { id: '01', content: '你好,中国' },
      { id: '02', content: '你好,程序员' },
      { id: '03', content: '你好,csdn' }
    ]
    export default class Detail extends Component {
      render() {
        // 接收params参数
        const { id, title } = this.props.match.params
        const findResult = DetailData.find((detailObj) => {
          // 如果某一项对象的id和我传过来的Id相等,findResult就等于这一项对象
          return detailObj.id === id
        })
        return (
          <ul>
            <li>ID: {id}</li>
            <li>TITLE: {title}</li>
            <li>CONTENT: {findResult.content}</li>
          </ul>
        )
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    🔥向路由组件传递search参数

    当点击消息1这个导航链接时,展示下方对应的Detail路由组件,并向这个组件传递search参数(ID,TITLE,CONTENT)信息。

    在这里插入图片描述

    向路由组件传递search参数:和params的写法有所不同

    {
      messageArr.map((msgObj) => {
        return (
          <li key={msgObj.id}>
    				{/* 向路由组件传递search参数 */}
    				<Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>
    				{msgObj.title}</Link>
          </li>
       )
     })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    注册路由时,search参数无需声明接收,正常注册路由即可,因为传递search参数的路径里有一个关键符存在

    <Route path="/home/message/detail" component={Detail} />
    
    • 1

    这样id,title参数就传递给了Detail组件,Detail组件可以通过this.props.location.search拿到参数。


    但是,接收到的参数是一个 urlencoded 格式的(例如 name=tom&age=18 就是urlencoded格式)

    在这里插入图片描述

    所以我们需要将 urlencoded格式 转换为一个 对象 的形式,需要借助一个query-string库

    // 安装query-string库
    npm i --save --include=dev query-string
    // 引入query-string
    import qs from 'query-string'
    
    • 1
    • 2
    • 3
    • 4

    query-string库里有两个方法stringfy()parse()

    // 将object转化为urlencoded
    qs.stringify()
    
    // 将urlencoded转化为object
    qs.parse()
    
    • 1
    • 2
    • 3
    • 4
    • 5

    // 接收search参数
    const { search } = this.props.location
    const { id, title } = qs.parse(search.slice(1))
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    Message->index.jsx:

    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}>
                      {/* 向路由组件传递search参数 */}
                      <Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>
                      {msgObj.title}</Link>
                    </li>
                  )
                })
              }
            </ul>
            <hr />
            {/* 注册路由 */}
            {/* search参数无需声明接收,正常注册路由即可 */}
            <Route path="/home/message/detail" component={Detail} />
          </div>
        )
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    Detail->index.jsx:

    import React, { Component } from 'react'
    // 引入query-string库
    import qs from 'query-string'
    
    const DetailData = [
      { id: '01', content: '你好,中国' },
      { id: '02', content: '你好,程序员' },
      { id: '03', content: '你好,csdn' }
    ]
    export default class Detail extends Component {
      render() {
        // 接收search参数
        const { search } = this.props.location
        const { id, title } = qs.parse(search.slice(1))
    
        const findResult = DetailData.find((detailObj) => {
          // 如果某一项对象的id和我传过来的Id相等,findResult就等于这一项对象
          return detailObj.id === id
        })
        return (
          <ul>
            <li>ID: {id}</li>
            <li>TITLE: {title}</li>
            <li>CONTENT: {findResult.content}</li>
          </ul>
        )
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    🔥向路由组件传递state参数

    前面学的两个参数给组件传递的信息会在地址栏中展示出来,例如:localhost:3000/home/message/detail/?id=01&title=消息1,这是传递search参数的地址。

    但是,传递state参数不会在地址栏中显示出来

    向路由组件传递state参数:

    {
      messageArr.map((msgObj) => {
        return (
          <li key={msgObj.id}>
            {/* 向路由组件传递state参数 */}
    		<Link to={{ pathname: '/home/message/detail', state: { id: msgObj.id, title: msgObj.title } }}>
    		{msgObj.title}</Link>
    </li>
    )
    })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    注:这里的to属性要写成一个对象的形式(传递params和search参数都是字符串形式),对象有两个属性分别是:pathname以及state,需要传递的参数就放在state中。

    注册路由时,search参数无需声明接收,正常注册路由即可。

    <Route path="/home/message/detail" component={Detail} />
    
    • 1

    这样id,title参数就传递给了Detail组件,Detail组件可以通过this.props.location.state拿到参数。

    // 接收state参数
    const { id, title } = this.props.location.state
    
    • 1
    • 2

    在这里插入图片描述

    Message->index.jsx:

    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}>
                      {/* 向路由组件传递state参数 */}
                      <Link to={{ pathname: '/home/message/detail', state: { id: msgObj.id, title: msgObj.title } }}>
                      {msgObj.title}</Link>
                    </li>
                  )
                })
              }
            </ul>
            <hr />
            {/* 注册路由 */}
            {/* state参数无需声明接收,正常注册路由即可 */}
            <Route path="/home/message/detail" component={Detail} />
          </div>
        )
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    Detail->index.jsx:

    import React, { Component } from 'react'
    
    const DetailData = [
      { id: '01', content: '你好,中国' },
      { id: '02', content: '你好,程序员' },
      { id: '03', content: '你好,csdn' }
    ]
    export default class Detail extends Component {
      render() {
        // 接收state参数
        const { id, title } = this.props.location.state
    
        const findResult = DetailData.find((detailObj) => {
          // 如果某一项对象的id和我传过来的Id相等,findResult就等于这一项对象
          return detailObj.id === id
        })
        return (
          <ul>
            <li>ID: {id}</li>
            <li>TITLE: {title}</li>
            <li>CONTENT: {findResult.content}</li>
          </ul>
        )
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    有一个问题:当刷新页面,页面内容不会改变,原因是history下保存着state数据,当清除浏览器缓存,重新打开页面,数据会丢失。改为如下代码,页面刷新不会报错。

    // 接收state参数
    const { id, title } = this.props.location.state || {}
    
    const findResult = DetailData.find((detailObj) => {
      // 如果某一项对象的id和我传过来的Id相等,findResult就等于这一项对象
      return detailObj.id === id
    }) || {}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    🔥总结三种向路由组件传参的方式

    params参数:

    1. 路由链接(携带参数):to=“/demo/test/tom/18”>详情

    2. 注册路由(声明接收):path=“/demo/test/:name/:age” component={Test}/>

    3. 接收参数: this.props.match.params

    search参数:

    1. 路由链接(携带参数):to=“/demo/test?name=tom&age=18”>详情

    2. 注册路由(无需声明,正常注册即可):path=“/demo/test” component={Test}/>

    3. 接收参数: this.props.location.search

    4. 备注:获取到的search是urlencoded编码字符串,需要借助querystring解析。

    state参数:

    1. 路由链接(携带参数):to={{pathname:‘/demo/test’,state: {name: ‘tom’,age:18}}}>详情

    2. 注册路由(无需声明,正常注册即可):path=“/demo/test” component={Test}/>

    3. 接收参数: this.props.location.state

    4. 备注:如果不用BrowserRouter,刷新保留不住参数,因为BrowserRouter的history里保留了参数信息。

    今天的分享就到这里啦 ✨
    如果对你有帮助的话,还请👉🏻关注💖点赞🤞收藏⭐评论🔥哦
    不定时回访哟🌹

  • 相关阅读:
    Spring Cloud 拉取 Nacos 中配置文件
    idea如何设置jvm大小
    JS中递归函数
    [JavaEE]计算机是如何工作的
    YOLOv7移植经验分享
    C#自定义窗体更换皮肤的方法:创建特殊窗体
    ZMQ之面向服务的可靠队列(管家模式)
    selenium 元素定位
    【小程序源码】经典语录大全多种分类语录
    一文带你理解@RefreshScope注解实现动态刷新原理
  • 原文地址:https://blog.csdn.net/xuxuii/article/details/125757000