如何做出反应路由器递归创建的网页?

问题描述 投票:3回答:1

我在这里讲的这个例子:https://reacttraining.com/react-router/web/example/recursive-paths

import React from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";

const PEEPS = [
  { 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] }
];

function find(id) {
  return PEEPS.find(p => p.id == id);
}

function RecursiveExample() {
  return (
    <Router>
      <Person match={{ params: { id: 0 }, url: "" }} />
    </Router>
  );
}

function Person({ match }) {
  let 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>
  );
}

export default RecursiveExample;

在这个例子中,我明白了递归是如何工作的,在一步一个脚印。当什么混淆我,是(在Mini浏览器),如果我把这个链接直接刷新页面,/1/0/3/2/3/2,或任何其他嵌套的例子后,如何做出反应路由器知道要呈现在正确的顺序组成部分。有与之相匹配的+ /:id1/:id2/:id3等没有显式路由路径

我知道这是不可行的,因为它可以去,直到无穷大,但如何做出反应路由器能够算出这个?

javascript reactjs react-native react-router
1个回答
1
投票

TLDR;这里的主要诀窍是Person组件拿着Route只要呈现pathRoute的URL匹配使自身各一次。


细节

按照设计,传递到路由的component支柱组件呈现,只有当路由的path道具页面的URL匹配。

{/* Something will get rendered when the URL /whatever matches the URL of the page */}
<Route path="/whatever" component={Something}>

因为我们只在渲染点击嵌套Person(有自己的Route),我们就可以无限期地产生这些递归路线。

每一个Person渲染的时候,它呈现在其中一个Route作为排序为下Person占位符。

function Person({ match }) {
  // ...

  return (
    <div>
      {/* ... */}
      {/* this route is a placeholder for the next Person */}
      <Route path={`${match.url}/:id`} component={Person} />
    </div>
  );
}

如果其所属PersonRoute的URL匹配此下一path获取呈现。所属Routepath是父加上另一个ID,即match.url + '/:id'的URL。

这是我们如何得到递归渲染。 Person使这使得它呈现一个Route一个Person一个Route ......这重复进行,直到最后呈现Routepath不匹配的页面URL。

注:match prop传递由Route到作为传递的组件component支撑成Route。这是Person如何访问它。

有一点要注意的是:应用程序总是Michelle的朋友(即与id0人的朋友),因为开始:

function RecursiveExample() {
  return (
    <Router>
      {/* This part of the code passes in a fake `match` prop to always start of the app from Michelle's point of view */}
      <Person match={{ params: { id: 0 }, url: "" }} />
    </Router>
  );
}

这意味着,不管你第一次打开网页或/0/1/2刷新页面,路由器做出反应总是呈现Michelle因为这会使嵌套Person第一<Route path='/:id' component={Person} />

这意味着应用程序的初始状态始终是这样的:

<RecursiveExample>
  <BrowserRouter>
    <Person>
      <Route path="/:id" />
    </Person>
  </BrowserRouter>
</RecursiveExample>

其呈现为:

app always starts with friends of Michelle

如果应用程序在/加载,呈现在上述状态下停止,直到我们开始与应用程序交互。

然而,如果我们刷新页面在/0/1/2,渲染将继续。如上图所示的初始状态被渲染后,反应路由器会发现,从path <Route path="/:id" />/0/1/2 URL匹配(通过采取0忽略其它),填补了id0并呈现下一个Person(具有id0) 。

注:以上URL匹配工作,因为一个Route的默认匹配策略是在路径的末尾忽略任何额外的字符。这就是为什么/:id匹配/0/1/2,该id0/1/2部分被忽略。我们可以使用exact prop迫使对手是,嗯,准确的,但那么这将打破递归的行为,即/:id只会匹配/0但不/0/1/2

在这一点上我们的树看起来像:

<RecursiveExample>
  <BrowserRouter>
    <Person>
      <Route path="/:id" {/* this matches /0 */}
        <Person>
          {/* we're here during the rendering stage */}
        </Person>
      </Route>
    <Person>
  </BrowserRouter>
</RecursiveExample>

在这一阶段呈现的人恰好Michelle再次(因为id 0)是。

Second stage also shows friends of Michelle

Person现在重复此过程。它使得自己的嵌套Route,现在有一个path/0/:id(因为它加到/:id父URL)和component再次为Person。由于/0/:id仍然匹配/0/1/2(id为现在1),我们呈现下一个Person

在这一点上的树是:

<RecursiveExample>
  <BrowserRouter>
    <Person>
      <Route path="/:id" {/* this matches /0 */}
        <Person>
          <Route path="/0/:id"> {/* this matches /0/1 */}
            <Person>
              {/* we're here during the rendering stage */}
            </Person>
          </Route>
        </Person>
      </Route>
    <Person>
  </BrowserRouter>
</RecursiveExample>

和树现在显示与id等于1的人的朋友:

Now we show friends of Sean

你能看出这是怎么回事?

此过程重复进行,直到在最后呈现path不匹配的URL提供的RoutePerson。在/0/1/2 URL刷新的情况下,这将是与Route path/0/1/2/:id

这是最后的阵营树的样子:

<RecursiveExample>
  <BrowserRouter>
    <Person>
      <Route path="/:id" {/* this matches /0 */}
        <Person>
          <Route path="/0/:id"> {/* this matches /0/1 */}
            <Person>
              <Route path="/0/1/:id"> {/* this matches /0/1/2 */}
                <Person>
                  <Route path="/0/1/2/:id" /> {/* this isn't matched yet */}             
                </Person>
              </Route>
            </Person>
          </Route>
        </Person>
      </Route>
    <Person>
  </BrowserRouter>
</RecursiveExample>

这是最终的应用程序状态:

final rendered state


现在,我们是否确实在/0/1/2刷新页面或点击链接获得它的行为是一样的。

重要的是要记住,它是控制什么被渲染的网址是很重要的。

当开始在经由刷新或通过手动键入它特定URL的应用程序,路由器做出反应穿过嵌套Person自动地再现相(上面的前几个示出),只要每个渲染路由的路径的URL相匹配。

在另一方面,每次我们点击一​​个链接到一个特定的URL,我们手动触发URL变化,这触发下一个Person的呈现阶段。

无论我们手动输入网址或通过单击创建它,如果得到的URL是一样的,所呈现的应用程序是一样的好。所不同的是,我们如何得到最终的渲染状态。

© www.soinside.com 2019 - 2024. All rights reserved.