我在这里讲的这个例子: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
等没有显式路由路径
我知道这是不可行的,因为它可以去,直到无穷大,但如何做出反应路由器能够算出这个?
TLDR;这里的主要诀窍是Person
组件拿着Route
只要呈现path
的Route
的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>
);
}
如果其所属Person
的Route
的URL匹配此下一path
获取呈现。所属Route
的path
是父加上另一个ID,即match.url + '/:id'
的URL。
这是我们如何得到递归渲染。 Person
使这使得它呈现一个Route
一个Person
一个Route
......这重复进行,直到最后呈现Route
的path
不匹配的页面URL。
注:match
prop传递由Route
到作为传递的组件component
支撑成Route
。这是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
,渲染将继续。如上图所示的初始状态被渲染后,反应路由器会发现,从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
的人的朋友:
你能看出这是怎么回事?
此过程重复进行,直到在最后呈现path
不匹配的URL提供的Route
的Person
。在/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>
这是最终的应用程序状态:
现在,我们是否确实在/0/1/2
刷新页面或点击链接获得它的行为是一样的。
重要的是要记住,它是控制什么被渲染的网址是很重要的。
当开始在经由刷新或通过手动键入它特定URL的应用程序,路由器做出反应穿过嵌套Person
自动地再现相(上面的前几个示出),只要每个渲染路由的路径的URL相匹配。
在另一方面,每次我们点击一个链接到一个特定的URL,我们手动触发URL变化,这触发下一个Person
的呈现阶段。
无论我们手动输入网址或通过单击创建它,如果得到的URL是一样的,所呈现的应用程序是一样的好。所不同的是,我们如何得到最终的渲染状态。