码云笔记提示:你现在浏览的网站是镜像网站

请访问原网站:www.mybj123.com
声明:码云笔记唯一指定网址为:mybj123 .com,其他网址均为冒充,望周知!!!前端技术交流群:565733884

使用React路由器的递归路径

JavaScript 码云 186℃ 0评论

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

使用React路由器的递归路径

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

  这里的主要思想是,由于React Router只是组件,理论上,你可以为无限路由创建递归路由。秘密就在于建立正确的数据结构,这可以导致无限的路由。在本例中,我们将使用具有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 ] }
]

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

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

Michelle's Friends

  * Sean
  * Kim
  * David

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

Michelle's Friends

  * Sean
  * Kim
  * David

Kim's Friends

  * Michelle
  * Sean
  * David

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

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的路径名。考虑到这一点,链接的初始部分将是这样的

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

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

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

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

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

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

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

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

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时未定义。这个问题的解决办法比看上去简单。当我们第一次手动渲染时,我们需要像路由器那样给它传递一个属性匹配。

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方法获取朋友的信息。我们将为它创建一个辅助函数。

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) =&gt; users.find(p =&gt; p.id == id)

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

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

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

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条所述,我们需要确保我们也呈现了一个路由。

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>
  )
}

  完整的代码现在看起来是这样的

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组件的路由匹配,后者呈现链接列表和新路由。理论上,只要用户继续点击任何链接,这个过程就会一直持续下去。

转载请注明:码云笔记 » 使用React路由器的递归路径

喜欢 (2)or分享 (0)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(1)个小伙伴在吐槽
  1. 学习了,感谢分享
    潇潇尓2019-01-14 10:00 回复