web前端开发技术博客
当前位置: JavaScript > 使用React路由器的递归路径

使用React路由器的递归路径

2019-01-09 分类:JavaScript 作者:码云 阅读(72)

  因为ReactRouter只是组件,你可以做一些疯狂的事情,比如递归路由。在这篇文章中,我们将通过分解ReactRouter文档中的“递归路径”示例来了解它们是如何工作的。

使用React路由器的递归路径

  递归路由不是世界上最实用的东西,但它们确实展示了ReactRouter基于组件的路由方法的好处。

  这里的主要思想是,由于React Router只是组件,理论上,你可以为无限路由创建递归路由。秘密就在于建立正确的数据结构,这可以导致无限的路由。在本例中,我们将使用具有id、名称和朋友数组的人员数组。

1
2
3
4
5
6
const users = [
  { id: 0, name: 'Michelle', friends: [ 1, 2, 3 ] },
  { id: 1, name: 'Sean', friends: [ 0, 3 ] },
  { id: 2, name: 'Kim', friends: [ 0, 1, 3 ], },
  { id: 3, name: 'David', friends: [ 1, 2 ] }
]

  通过以这种方式设置这个数据结构,当我们呈现一个人时,我们将呈现他们所有的朋友作为链接。然后,当一个链接被点击时,我们将把那个人的所有朋友都呈现为链接,以此类推。每次点击一个链接,应用程序的路径名就会逐渐变长。

  最初,我们会看到/,UI是这样的

1
2
3
4
5
Michelle's Friends

  * Sean
  * Kim
  * David

  如果单击Kim,那么URL将变为/2(Kim的ID),UI将如下所示

1
2
3
4
5
6
7
8
9
10
11
Michelle's Friends

  * Sean
  * Kim
  * David

Kim'
s Friends

  * Michelle
  * Sean
  * David

  如果单击David,那么URL将变为/2/3(Kim的id和David的id),UI将像这样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Michelle's Friends

  * Sean
  * Kim
  * David

Kim'
s Friends

  * Michelle
  * Sean
  * David

David's Friends

  * Sean
  * Kim

  只要用户想点击链接,这个过程就会一直重复。

  一旦你建立了正确的数据结构,下一个重要步骤是继续呈现路由和一些链接。因为我们正在创建无限的路由,所以我们需要确保每次单击链接时都会呈现一个路由。如果没有,我们将不会得到更多的匹配,这意味着React Router将不会呈现更多的组件。在我们的链接和路由中,我们需要知道应用程序的当前路径名,这样我们就可以在每次单击链接时追加它(就像在上面的例子中,我们从/2到/2/3,等等)。幸运的是,React Router为我们提供了带有match.url的路径名。考虑到这一点,链接的初始部分将是这样的

1
<link to="{'{match.url}/${id}}'">

  我们渲染的路径会在相似的模式下匹配,然后渲染相同的组件。

1
<Route path={'${match.url}/:id'} component={Person}/>

  现在我们已经了解了基础知识,让我们开始构建将被递归呈现的组件Person。

  请记住,这个组件需要负责一些事情。

  1.它应该为每个特定的人的朋友呈现一个Link组件。

  2.它应该呈现与当前路径名+/:id匹配的路由组件。

  与所有递归问题一样,我们需要以某种方式“开始”递归。通常这涉及到调用函数,但是如果它是递归调用的组件,我们可以通过简单地创建元素来实现。

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
import React from 'react'
import {
  BrowserRouter as Router,
  Route,
  Link
} from 'react-router-dom'

const users = [
  { id: 0, name: 'Michelle', friends: [ 1, 2, 3 ] },
  { id: 1, name: 'Sean', friends: [ 0, 3 ] },
  { id: 2, name: 'Kim', friends: [ 0, 1, 3 ], },
  { id: 3, name: 'David', friends: [ 1, 2 ] }
]

const Person = ({ match }) => {
  return (
    <div>
      PERSON
    </div>
  )
}

class App extends React.Component {
  render() {
    return (
      <Router>
        <Person />
      </Router>
    )
  }
}

export default App

  现在我们需要做的是找出如何从用户数组中获取特定朋友的信息,这样我们就可以获取他们的名字并呈现他们的朋友。在这里大家可能会注意到这里有一个问题。最终Person会被路由器渲染,它会被传递一个属性匹配。我们将使用这个匹配道具获取当前路径名和(在用户的帮助下)人名和好友列表。问题是我们在主App组件中手动渲染Person来启动递归。这意味着匹配将在第一次呈现Person时未定义。这个问题的解决办法比看上去简单。当我们第一次手动渲染时,我们需要像路由器那样给它传递一个属性匹配。

1
2
3
4
5
6
7
8
9
class App extends React.Component {
  render() {
    return (
      <Router>
        <Person match={{ params: { id: 0 }, url: '' }}/>
      </Router>
    )
  }
}

  现在,每次渲染Person时,包括第一次,它都会被传递一个匹配属性,这个属性包含我们需要的两个东西,url来渲染我们的路由,链接和参数。id,这样我们就能知道渲染的是谁。

  好了,回到我们的主要目标。Person需要

  1、它应该为每个特定的人的朋友呈现一个Link组件。

  2、它应该呈现与当前路径名+/:id匹配的路由组件。

  在我们能够呈现任何链接之前,我们需要得到这个人的朋友。我们已经从match.params.id中知道了这个人的id。在数组中我们可以直接通过使用Array.find方法获取朋友的信息。我们将为它创建一个辅助函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const users = [
  { id: 0, name: 'Michelle', friends: [ 1, 2, 3 ] },
  { id: 1, name: 'Sean', friends: [ 0, 3 ] },
  { id: 2, name: 'Kim', friends: [ 0, 1, 3 ], },
  { id: 3, name: 'David', friends: [ 1, 2 ] }
]

const find = (id) => users.find(p => p.id == id)

const Person = ({ match }) =&gt; {
  const person = find(match.params.id)

  return (
    <div>
      PERSON
    </div>
  )
}

  现在我们有了person,让我们呈现一些包括每个朋友的链接的UI。

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
const users = [
  { id: 0, name: 'Michelle', friends: [ 1, 2, 3 ] },
  { id: 1, name: 'Sean', friends: [ 0, 3 ] },
  { id: 2, name: 'Kim', friends: [ 0, 1, 3 ], },
  { id: 3, name: 'David', friends: [ 1, 2 ] }
]

const find = (id) => users.find(p => p.id == id)

const Person = ({ match }) => {
  const person = find(match.params.id)

  return (
    <div>
      <h3>{person.name}’s Friends</h3>
      <ul>
        {person.friends.map((id) => (
          <li key={id}>
            <Link to={'${match.url}/${id}'}>
              {find(id).name}
            </Link>
          </li>
        ))}
      </ul>
    </div>
  )
}

  现在我们已经为每个人的朋友建立了一个链接,如第2条所述,我们需要确保我们也呈现了一个路由。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const Person = ({ match }) => {
  const person = find(match.params.id)
  return (
    <div>
      <h3>{person.name}’s Friends</h3>
      <ul>
        {person.friends.map((id) => (
          <li key={id}>
            <Link to={`${match.url}/${id}`}>
              {find(id).name}
            </Link>
          </li>
        ))}
      </ul>
      <Route path={'${match.url}/:id'} component={Person}/>
    </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
38
39
40
41
42
43
44
45
46
47
import React from 'react'
import {
  BrowserRouter as Router,
  Route,
  Link
} from 'react-router-dom'

const find = (id) => users.find(p => p.id == id)

const users = [
  { id: 0, name: 'Michelle', friends: [ 1, 2, 3 ] },
  { id: 1, name: 'Sean', friends: [ 0, 3 ] },
  { id: 2, name: 'Kim', friends: [ 0, 1, 3 ], },
  { id: 3, name: 'David', friends: [ 1, 2 ] }
]

const Person = ({ match }) => {
  const person = find(match.params.id)

  return (
    <div>
      <h3>{person.name}’s Friends</h3>
      <ul>
        {person.friends.map((id) => (
          <li key={id}>
            <Link to={`${match.url}/${id}`}>
              {find(id).name}
            </Link>
          </li>
        ))}
      </ul>
      <Route path={'${match.url}/:id'} component={Person}/>
    </div>
  )
}

class App extends React.Component {
  render() {
    return (
      <Router>
        <Person match={{ params: { id: 0 }, url: '' }}/>
      </Router>
    )
  }
}

export default App

  第一次呈现Person时,我们向它传递一个模拟匹配对象。然后,Person呈现链接列表以及匹配这些链接的路由。当单击链接时,该路由与呈现另一个Person组件的路由匹配,后者呈现链接列表和新路由。理论上,只要用户继续点击任何链接,这个过程就会一直持续下去。

「如果觉得我的文章对您有用,请帮助本站成长」

赞(2) 打赏

觉得文章有用就打赏一下文章作者

支付宝
微信
2

觉得文章有用就打赏一下文章作者

支付宝
微信

上一篇:

下一篇:

共有 1 条评论 - 使用React路由器的递归路径

  1. 潇潇尓 Linux Chrome 62.0.3202.84

    学习了,感谢分享

博客简介

码云笔记: mybj123.com,一个关注Web前端开发技术的博客,主要记录和总结前端工作中常用的知识及我的生活。
更多博客详情请看关于博客

圈子

关注微信公众号
关注微信公众号

精彩评论

服务热线:
 13888888888

 QQ在线交流