[英]How does React Router recursively create pages?
我在这里谈论这个例子: 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;
在这个例子中,我理解递归如何一次一步地工作。 令我困惑的是,当(在那个迷你浏览器中)如果我在刷新页面之后直接放入此链接, /1/0/3/2/3/2
1/0/3/2/3/2或任何其他嵌套示例时,React Router如何知道以正确的顺序呈现组件。 没有明确的路径路径匹配+ /:id1/:id2/:id3
等。
我知道这是不可行的,因为它可以直到无限,但React Router如何能够解决这个问题呢?
TLDR; 这里的主要技巧是,只要呈现的Route
的path
与URL匹配,持有Route
的Person
组件每次都会呈现自身。
细节
按照设计,只有当Route的path
prop与页面的URL匹配时,才会传递传递给Route的component
prop的component
。
{/* 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>
);
}
如果其拥有的Route
的path
与URL匹配,则会呈现此下一个Person
。 拥有Route
的path
是父级的URL加上另一个id,即match.url + '/:id'
。
这就是我们如何获得递归渲染。 Person
呈现一个Route
这使得一个Person
这使得一个Route
......这重复进行,直到最后呈现的Route
的path
不匹配的页面URL。
注意: match
prop由Route
传递到作为component
prop传递到该Route
的component
。 这就是Person
可以访问它的方式。
有一点需要注意:应用程序总是从Michelle
的朋友(即id
为0
的人的朋友)开始,因为:
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>
其呈现为:
如果应用程序已加载到/
,则渲染将停止在上述状态,直到我们开始与应用程序进行交互。
但是,如果我们在/0/1/2
0/1/2刷新页面,渲染将继续。 上面所示的初始状态被呈现之后,阵营路由器将找出path
,从<Route path="/:id" />
匹配/0/1/2
的URL(通过取0
忽略其余部分),填补id
为0
并渲染下一个Person
( id
为0
那个)。
注意:上面的URL匹配是有效的,因为Route
的默认匹配策略是忽略路径末尾的任何多余字符。 这就是为什么/:id
匹配/0/1/2
, id
为0
并忽略/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
)。
此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
的人的朋友:
你能看出这是怎么回事吗?
重复此过程,直到在最后一个呈现的Person
中呈现的Route
的path
与URL不匹配。 在刷新/0/1/2
URL的情况下,这将是具有path
/0/1/2/:id
的Route
。
这是最终的React树的外观:
<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>
这是最终的申请状态:
现在,无论我们实际刷新页面在/0/1/2
还是单击链接到达它,行为都是一样的。
重要的是要记住,它是控制渲染内容的URL。
通过刷新或通过手动键入特定URL启动应用程序时,只要每个呈现的路径的路径与URL匹配,React Router就会自动(上面显示的前几个)遍历嵌套的Person
呈现阶段。
另一方面,每次我们点击指向特定URL的链接时,我们都会手动触发URL更改,从而触发下一个Person
的呈现阶段。
我们是手动键入URL还是通过单击创建URL,如果生成的URL相同,则呈现的应用程序也是相同的。 不同之处在于我们如何进入最终渲染状态。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.