什么是路由?为什么单页 Web 应用需要“路由”?

28

我了解到像 React Router(https://github.com/ReactTraining/react-router)这样的SPA路由库有助于解析URL并将应用程序放入状态机的相应状态中。

除此之外,路由还有什么其他作用吗?

首先,为什么需要路由?

为什么URL如此重要?例如,在桌面应用程序中没有URL,那么在Web应用程序中URL有什么大不了的呢?


所有的URL都是URI,而桌面端使用的是URI。 - Enzokie
很好的问题,我也正想问同样的问题。这可能会变得越来越相关,原因有两个:(1)Web应用程序趋向于变得越来越类似于(无需路由)桌面应用程序:PWA。(2)在React状态中管理“路由”非常容易。人们需要那个状态,所以可以添加额外的信息。仍然正确的是,路由保护免受应用程序之外的导航(F5,后退按钮等),并且它可以帮助将应用程序的特殊视图加入书签。但是这些功能可能不值得费心去实现路由。 - Carsten Führmann
5个回答

36

我也有这个问题:“为什么我们需要路由?”你可以完全不使用路由编写应用程序。代码可能会变得混乱,但这并不是不可能的。

我使用路由的最大原因是,如果用户点击浏览器的“后退”按钮(同样适用于“前进”按钮),他们将无法在应用程序内导航。用户可能希望使用他们之前加载的不同“页面”的历史记录在应用程序内导航。相反,他们将被扔出Web应用程序。单击刷新按钮也会将它们抛到应用程序的根目录。

从用户的角度来看,它是一个常规的Web应用程序(他们不需要知道它是如何设计的:SPA还是其他方式),它应该像任何Web应用程序/网站一样工作。路由确保了这一点,不是吗?


20

这是一个非常好的问题,但我认为它没有被讨论得足够多。简短的答案是,在单页Web应用中,通常不需要使用路由。如果您正在构建的应用程序不需要其页面被Google索引,并且您不关心或不希望用户能够书签页面,那么就没有必要实现路由。

在SPA中,路由会增加额外的复杂性和工作量,因此如果可以避免使用它,应该尽量避免。当然,像Angular和React这样的现代框架提供了使路由变得更容易的功能,但即使如此,有些事情可能仍然很难用路由来完成,例如在页面之间进行动画切换。

一个适合使用无需路由的Web应用程序的好例子是多页表单,您想要控制用户的通过并可能防止他们返回到已经失效的页面。使用路由实现这样的表单将是一场噩梦,因为您必须防止用户在其历史记录中访问某些页面。

要理解SPA中的路由是什么,问问自己是有用的。很容易把它想象成一个“网页”,但实际上它是一个状态,当你在不同的路由之间导航时,你真正做的是在不同的应用程序状态之间导航。应用程序外观在不同状态之间可能会改变,但这只是次要的。所以路由的作用是为用户提供返回应用程序特定状态的手段。 只有在希望用户能够返回应用程序特定状态时,才应该在SPA中实现路由。 另一种更有用的做法是实现撤消和重做机制。
当然,即使没有路由,你仍然需要关心用户点击“历史记录”按钮时发生的事情,但是这时候你只需弹出模态警告框,警告用户如果继续导航将要离开应用程序。

2
这是一个非常深思熟虑的答案。我自己也遇到过这个问题。如果你的SPA应该以更流畅的方式运行,那么路由器会增加更多的问题而解决不了任何问题。路由假设你可以独立地访问任何URL哈希,但在流程中,当前视图往往取决于先前视图的状态和输入。 - Matías Navarro Carter
也许我问得太幼稚了,但您能否告诉我如何通过路由更好地控制单击“返回”按钮时的行为?在路由后单击“返回”按钮会发生什么? - Whirl Mind
我不太明白你的问题。能否请你重新表述一下? - Richard Hunter

10
在桌面应用程序中,你有按钮和其他控件来获取所需内容。因此,在 UI 应用程序中,路由将是所有 UI 控件的集合。 另一方面,在 Web 应用程序中,所有功能都通过某些文本访问,即链接和参数。
URL 是访问功能的路径。路由就像是根据提供的 URL 和参数决定调用哪个功能的机制。
因此,基本上路由是 URL 和 Web 服务器功能之间的映射关系。

5
在单页应用程序中,路由用于加载Web应用程序的某些部分,例如yourappurl.com/profile/userid/将加载具有与userid相对应的正确用户配置文件的SPA的配置文件部分。这可以在您提供的GitHub示例中看到。
<Router history={browserHistory}>
<Route path="/" component={App}>
  <Route path="about" component={About}/>
  <Route path="users" component={Users}>
    <Route path="/user/:userId" component={User}/>
  </Route>
  <Route path="*" component={NoMatch}/>
</Route>

SPA是指通常有一个index.html作为“主视图”,然后根据路由,使用React、AngularJS等框架添加/删除index.html的某些部分。


3
好的,但这是为什么呢?这有何好处?没有任何桌面应用程序具有此功能。为什么需要这个? - jhegedus
1
@jhegedus 这确实是任何类型路由的唯一方法,这似乎很直观,因为Web的本质就是基于URL。我猜某个时候有人决定在单页应用程序上也应该使用URL进行路由。对我来说,这似乎也是违反直觉的(相当长的一段时间),但如果你仔细想想,否则你如何隐藏/显示页面的部分呢?当然,你只能编写相对路径,但路径= URL。你明白我的意思吗?你必须有一个路径,而路径在Web上意味着URL。你不能像iOS等平台那样在视图控制器之间进行过渡。 - tech4242
4
你可以通过使用 JavaScript 操纵 DOM 元素来隐藏或显示页面的其他部分。DOM 是与 URL 独立的,这意味着你可以自由地更改页面上的元素而不会影响到 URL。 - jhegedus
3
@jhegedus 正确,但这正是框架在后台完成的 :) 它只是通过让您像在桌面应用程序上路由一样来使事情变得更容易。它有助于代码重用等,因为您不必手动显示/隐藏元素等。当您从一个部分视图路由到另一个部分视图时,它会在后台为您执行许多 UI 操作,这样您就可以专注于应用程序的用户界面而不是在编写原始 JS 代码时进行的整理处理。 - tech4242

2

我时不时会有同样的问题。

我想说,在单页应用中,路由器是一个组件层次结构助手。

正如@tech4242所指出的那样,在iOS中我们没有像segue这样的东西。那么如果我们不使用路由器来帮助用户导航,我们应该使用什么呢?我们在这里讨论的是单页应用程序。因此,我们可以在存储或状态中管理这个问题。是的,这是可行的,但不是首选。

试着从使用基于组件的库(React或Vue)的角度来考虑这个问题。使用路由器帮助我们为特定路由使用某个组件。当用户在不同的路由之间来回移动时,我们依赖路由来告诉我们显示哪个组件。我们只需将组件与特定路由耦合在一起,这使得我们的根组件(通常称为App)清晰、易于维护和可读性高。如果没有路由器,根组件或状态将变得混乱且难以维护。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接