<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ 路由 - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ freeCodeCamp 是一个免费学习编程的开发者社区，涵盖 Python、HTML、CSS、React、Vue、BootStrap、JSON 教程等，还有活跃的技术论坛和丰富的社区活动，在你学习编程和找工作时为你提供建议和帮助。 ]]>
        </description>
        <link>https://www.freecodecamp.org/chinese/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ 路由 - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/chinese/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 09 Jun 2026 10:01:23 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/chinese/news/tag/routing/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ 做轮子·实现路由的两种思路 ]]>
                </title>
                <description>
                    <![CDATA[ > 本文指的路由，不是路由器，也不是PS4（5？），是特指后端API框架里的router，前端路由也有可以有借鉴的部分，但本文不承诺正确性。 今天不妨讨论个不那么大的话题，restful路由的实现。 我们眼中的路由是什么样子的？ 我们常见的路由是这个样子的 router.get('/what/i/want', ... ); router.get('/what/i/hate', ... ); router.get('/what/u/want', ... ); 我们今天就来讨论一下，当我们想访问 /what/i/want时，都有些什么玄机。 路由是怎么工作的 首先明确路由的目的，就是根据接收到的路径字符串，找到对应的业务处理逻辑。 为了弄明白业界常用框架对这一块，我专门查阅了若干开发框架的源码（express, koa, Gin, kratos, Lumen），最终概括成两种实现手段。  * Key - Value 型路由  * Tree 型路由 现在来分析一下两种路由的特性和适用场景。 Key - Value 型路由 这个模式，形如我们熟悉的hash tab ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/how-backend-router-work/</link>
                <guid isPermaLink="false">5f5103dccd07b005bfb5aeb6</guid>
                
                    <category>
                        <![CDATA[ 路由 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ RESTful API ]]>
                    </category>
                
                    <category>
                        <![CDATA[ 正则表达式 ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ 开发者小蓝 ]]>
                </dc:creator>
                <pubDate>Sat, 13 Feb 2021 09:00:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2020/09/318-02.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <blockquote>
<p>本文指的路由，不是路由器，也不是PS4（5？），是特指后端API框架里的router，前端路由也有可以有借鉴的部分，但本文不承诺正确性。</p>
</blockquote>
<p>今天不妨讨论个不那么大的话题，<strong>restful路由</strong>的实现。</p>
<h4 id="">我们眼中的路由是什么样子的？</h4>
<p>我们常见的路由是这个样子的</p>
<pre><code>router.get('/what/i/want', ... );

router.get('/what/i/hate', ... );

router.get('/what/u/want', ... );
</code></pre>
<p>我们今天就来讨论一下，当我们想访问 <code>/what/i/want</code>时，都有些什么玄机。</p>
<h4 id="">路由是怎么工作的</h4>
<p>首先明确路由的目的，就是根据接收到的路径字符串，找到对应的业务处理逻辑。</p>
<p>为了弄明白业界常用框架对这一块，我专门查阅了若干开发框架的源码（express, koa, Gin, kratos, Lumen），最终概括成两种实现手段。</p>
<ul>
<li>Key - Value 型路由</li>
<li>Tree 型路由</li>
</ul>
<p><img src="https://lanhaooss.oss-cn-shenzhen.aliyuncs.com/images/328/318-03.jpg" alt="318-03" width="600" height="400" loading="lazy"></p>
<p>现在来分析一下两种路由的特性和适用场景。</p>
<h4 id="keyvalue">Key - Value 型路由</h4>
<p>这个模式，形如我们熟悉的<code>hash table</code>、字典，通过键值对维护这<code>uri</code>与函数的对应关系。</p>
<p><img src="https://lanhaooss.oss-cn-shenzhen.aliyuncs.com/images/328/318-04.jpg" alt="318-04" width="600" height="400" loading="lazy"></p>
<p>我们理所当然地认为，只要确定的访问地址， 如<code>/what/i/want</code>, 就能立即找到对应的业务方法<code>functionA</code>，是个铁骨铮铮的 <code>O(1)</code>操作。</p>
<blockquote>
<p>当一个操作的复杂度与规模无关，就是一个O(1)的操作。比如无论我的 uri 地址有多少个，只要确定 uri 的值，总是能立即确定与之对应的方法。</p>
</blockquote>
<p><strong>然而遗憾的是，我就没见到有这么实现路由的。</strong></p>
<p>真实的情况是，</p>
<p><strong>Key - Value 型路由会从前到后一个一个比较，直到找到一个能匹配当前 uri 的key，再确定它对应的 function</strong></p>
<p>所以实际上它是一个 <code>O(n)</code> 操作，平均情况下需要比较 <code>N/2</code> 次才能定位。</p>
<blockquote>
<p>一个 <code>O(n)</code> 操作，其复杂度会随着数据规模的增大而线性增长，而我们普遍认为，在经过多次测量观察后，平均情况下会在 N/2 的位置上找到答案。</p>
</blockquote>
<p>疑惑归疑惑，正如本文的作者一样，做轮子人并不是疯了。</p>
<p><strong>之所以采用这种逐个匹配的模式，是因为我们的uri通过是不能确定的。</strong></p>
<p>比如， 一些<code>uri</code>里甚至包含了变量</p>
<pre><code>GET /staff/9527

GET /staff/709394
</code></pre>
<p>所以，我们通常是吧 <strong>Key - Value</strong>里面的<strong>Key</strong>，设计成<strong>正则表达式</strong>。</p>
<p>相应的，在理论研究中的<strong>Hash Table</strong>也会被<strong>顺序表</strong>替代。</p>
<p>总结起来就是，</p>
<hr>
<p>当我们访问一个确定的<code>uri</code>时，路由会尝试按顺序逐个匹配注册好的<strong>正则表达式</strong>，直到<code>match</code>到一个结果。</p>
<p>否则，返回 404</p>
<hr>
<p><strong>升华一下</strong></p>
<blockquote>
<p>如何压榨这种路由的性能？ 既然是按顺序逐个匹配，那我们就根据自己的业务特点，把可能访问量最大的接口注册到前面去。</p>
<p>也有一些框架是会动态调整顺序的，这就是题外话。</p>
</blockquote>
<p>--</p>
<h4 id="tree">Tree 型路由</h4>
<p>这个模式相对来说思路要骚一些。</p>
<p>它把<code>uri</code>按照<code>/</code>分割一个，在之前构建好的路由树里，一个节点一个几点的检索，直到成功走到一个叶子节点。</p>
<p><img src="https://lanhaooss.oss-cn-shenzhen.aliyuncs.com/images/328/318-05.jpg" alt="318-05" width="600" height="400" loading="lazy"></p>
<p>与上面提到的<code>N/2</code>次比较相比，这个模式的比较次数比较稳定，就是<code>uri</code>的层数。</p>
<blockquote>
<p>对于 <code>/what/i/want</code>，我们认为它是一个 3 层的地址，如果这个地址是存在的，那么在比较3次以后，就能找到对应的答案。</p>
</blockquote>
<p><strong>真是 “遇事不决，数据结构” 啊</strong></p>
<p>这种树形的路由特别适合<code>restful</code>风格的API，因为我们设计<code>restful</code>接口的时候，通常每一层都有它自己的<strong>类聚含义</strong>，所以它会构建出一棵非常标致的树。</p>
<p><img src="https://lanhaooss.oss-cn-shenzhen.aliyuncs.com/images/328/318-06.jpg" alt="318-06" width="600" height="400" loading="lazy"></p>
<p><strong>问(gang)题(jing)来了</strong></p>
<p>Q1: 请问 Tree 型路由 怎么解决<code>uri</code>里有变量的情况呢？</p>
<blockquote>
<p>很巧妙。当你注册的路由包含了变量，比如 <code>/staff/:id</code>这样的，它会在这个树<code>staff</code>的子节点里，也就第二层，创建一个通配节点（可能是<code>*</code>）。</p>
<p>它认为，不管<code>staff</code>后面跟什么内容，都能匹配这个<code>*</code></p>
</blockquote>
<p>Q2: 如果我同时注册了<code>/staff/:id</code>和<code>/staff/list</code>呢？会匹配错吗？</p>
<blockquote>
<p>考虑到这种情况，Tree 型路由的一般实现是，优先匹配确定值<code>list</code>，次要匹配<code>*</code>。</p>
<p>有这种情况是要复杂一些，不过并不影响它的整体复杂度。</p>
</blockquote>
<h4 id="">最后，作者喜欢哪一种？</h4>
<p>尽管我在最近开发的一个框架里使用了<strong>Tree 型路由</strong>，这并不代表我的倾向。</p>
<p>实际上应该根据上文提到两种模式各自的特点，选择最好的实现方式。</p>
<p><strong>当然</strong></p>
<p>我期待读者自己做轮子的时候，能做出一个根据开发者注册的路由的特点，自动选择路由模型的<strong>智能路由</strong>。</p>
<hr>
<p>好了，今天先到这里，下次再会。</p>
<!--kg-card-end: markdown--> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ React Router 入门指南 ]]>
                </title>
                <description>
                    <![CDATA[ 有时你只有 5 分钟的空闲时间，与其把这时间浪费在社交媒体上，不如快速了解一下React-Router！在本教程中，我们将通过为 Scrimba 针织店网站构建导航来学习 React中路由的基础知识。这个示例不是真实的，但也许有一天... ;） 如果你想了解这个主题，可以参加我的高级 React 课程 [https://scrimba.com/g/greact?utm_source=freecodecamp.org&utm_medium=referral&utm_campaign=router_article] ，或者如果你仍然是初学者，请查看我的 React 入门课程 [https://scrimba.com/g/glearnreact?utm_source=freecodecamp.org&utm_medium=referral&utm_campaign=router_article] 。 React-Router 是什么 许多现代网站实际上是由一个页面组成的。它们看起来就像是多个页面，因为它们包含呈现为单独页面的组件。这些通常被称为 SPA——单页应用程序。 从根本上说，R ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/react-router-in-5-minutes/</link>
                <guid isPermaLink="false">5feee8cf39641a0517d52f79</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ 路由 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ 前端开发 ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chengjun.L ]]>
                </dc:creator>
                <pubDate>Sat, 02 Jan 2021 02:20:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2021/01/1609494823003.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>有时你只有 5 分钟的空闲时间，与其把这时间浪费在社交媒体上，不如快速了解一下React-Router！在本教程中，我们将通过为 Scrimba 针织店网站构建导航来学习 React中路由的基础知识。这个示例不是真实的，但也许有一天... ;）</p><p>如果你想了解这个主题，可以参加我的<a href="https://scrimba.com/g/greact?utm_source=freecodecamp.org&amp;utm_medium=referral&amp;utm_campaign=router_article">高级 React 课程</a>，或者如果你仍然是初学者，请查看我的 <a href="https://scrimba.com/g/glearnreact?utm_source=freecodecamp.org&amp;utm_medium=referral&amp;utm_campaign=router_article">React 入门课程</a>。</p><h3 id="react-router-"><strong>React-Router 是什么</strong></h3><p>许多现代网站实际上是由一个页面组成的。它们看起来就像是多个页面，因为它们包含呈现为单独页面的组件。这些通常被称为 SPA——单页应用程序。</p><p>从根本上说，React Router 的作用是根据 URL 中使用的路由有条件地显示某些组件（<code>/</code> 表示主页，<code>/about</code> 表示关于页面等）。</p><p>例如，我们可以使用 React Router 将 <em><em>www.knit-with-scrimba.com/</em> </em>连接到 <em><em>www.knit-with-scrimba.com/about</em></em> or <em><em>www.knit-with-scrimba.com/shop</em>。</em></p><h3 id="-"><strong>听起来不错——我怎么使用它呢？</strong></h3><p>要使用 React Router，首先必须使用 NPM 安装它：</p><pre><code class="language-bash">npm install react-router-dom
</code></pre><p>另外，你也可以使用 <a href="https://scrimba.com/c/cNq8MzCr">Scrimba 的这个代码示例</a>，那里已经编写了完整的代码。</p><p>你需要从 <code>react-router-dom</code> 包中导入 BrowserRouter，Route 和 Switch：</p><pre><code class="language-js">import React, { Component } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
</code></pre><p>在我的示例中，我将登录页面与其他两个“<code>Shop</code>（商店）”和“<code>About</code>（关于）”页面（实际上只是组件）链接起来。</p><p>首先，你需要设置你的应用程序，以与 React Router 一起使用。渲染的所有内容都需要放入 <code>&lt;BrowserRouter&gt;</code> 元素内。因此请先将你的 App 放在里面。该组件执行显示你提供的各种组件的所有逻辑。</p><pre><code class="language-js">// index.js
ReactDOM.render(
    &lt;BrowserRouter&gt;
        &lt;App /&gt;
    &lt;/BrowserRouter&gt;, 
    document.getElementById('root')
)
</code></pre><p>接下来，在你的 App 组件中，添加 <code>Switch</code> 元素（打开和关闭标签）。这些确保每次仅渲染一个组件。如果我们不使用它，我们可以默认使用 <code>Error</code> 组件，稍后再编写。</p><pre><code class="language-js">function App() {
    return (
        &lt;main&gt;
            &lt;Switch&gt;
                
            &lt;/Switch&gt;
        &lt;/main&gt;
    )
}
</code></pre><p>现在该添加你的 <code>&lt;Route&gt;</code> 标签。这些是组件之间的链接，应放置在 <code>&lt;Switch&gt;</code> 标签内。</p><p>要告诉 <code>&lt;Route&gt;</code> 标签要加载哪个组件，只需添加 <code>path</code> &nbsp;属性和要用 <code>component</code> 属性加载的组件名称即可。</p><pre><code class="language-js">&lt;Route path='/' component={Home} /&gt;
</code></pre><p>许多主页 URL 是站点名称，后面跟着 <code>/</code>，例如 <em><em>www.knit-with-scrimba.com/</em></em>。在这种情况下，我们把 <code>exact</code> 添加到 Route 标签。这是因为其他 URL 也包含“ /”。因此，如果我们不告诉应用程序它只需要查找 <code>/</code>，则会加载第一个以匹配该路由的 URL，我们会遇到一个非常棘手的 bug。</p><pre><code class="language-js">function App() {
    return (
        &lt;main&gt;
            &lt;Switch&gt;
                &lt;Route path="/" component={Home} exact /&gt;
                &lt;Route path="/about" component={About} /&gt;
                &lt;Route path="/shop" component={Shop} /&gt;
            &lt;/Switch&gt;
        &lt;/main&gt;
    )
}
</code></pre><p>现在将组件导入应用程序。你可能希望将它们放在单独的“组件”文件夹中，以保持代码的清洁和可读性。</p><pre><code class="language-js">import Home from './components/Home';
import About from './components/About';
import Shop from './components/Shop';
</code></pre><p>关于我之前提到的错误消息，如果用户键入了错误的 URL，则会加载该错误消息。这就像普通的 <code>&lt;Route&gt;</code> 标签，但没有路径。错误组件包含 <code>&lt;h1&gt;Oops! Page not found!&lt;/h1&gt;</code>。不要忘记将它导入到应用程序中。</p><pre><code class="language-js">function App() {
    return (
        &lt;main&gt;
            &lt;Switch&gt;
                &lt;Route path="/" component={Home} exact /&gt;
                &lt;Route path="/about" component={About} /&gt;
                &lt;Route path="/shop" component={Shop} /&gt;
                &lt;Route component={Error} /&gt;
            &lt;/Switch&gt;
        &lt;/main&gt;
    )
}
</code></pre><p>到目前为止，我们的网站只能通过输入 URL 进行导航。为了给网站添加可点击的链接，我们使用 React Router 中的 <code>Link</code> 元素，并设置一个新的 <code>Navbar</code> 组件。同样的，不要忘记将新组件导入到应用程序中。</p><p>现在，为应用程序中的每个组件添加一个 <code>Link</code>，并使用 <code>to="URL"</code> 进行链接。</p><pre><code class="language-js">function Navbar() {
  return (
    &lt;div&gt;
      &lt;Link to="/"&gt;Home &lt;/Link&gt;
      &lt;Link to="/about"&gt;About Us &lt;/Link&gt;
      &lt;Link to="/shop"&gt;Shop Now &lt;/Link&gt;
    &lt;/div&gt;
  );
};
</code></pre><p>你的网站现在具有可单击的链接，可以在单页应用程序中导航了！</p><h3 id="--1"><strong>总结</strong></h3><p>我们已经完成了。如果你想轻松地在 React 应用程序中导航，请忘记锚标记，并添加React Router。它很干净，有条理，并且使添加和删除页面变得更加容易。</p><p>原文：<a href="https://www.freecodecamp.org/news/react-router-in-5-minutes/">Learn React Router in 5 Minutes - A Beginner's Tutorial</a>，作者：<a href="https://www.freecodecamp.org/news/author/bob/">Bob Ziroll</a></p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
