【问题标题】:AngularJS - How does $location html5Mode work?AngularJS - $location html5Mode 是如何工作的?
【发布时间】:2015-10-04 07:41:30
【问题描述】:

我问这个是因为现在有几次,我尝试使用$locationProvider.html5Mode(true) 命令和<base href="/"> 并在为我的项目调用脚本/样式/图像时遇到很多错误.我想一定是我做错了什么,但是您是否应该遵循某种文件夹结构,这样您就不会遇到这些错误?或者有没有我不太理解的base href 的具体工作方式?

最近,我想在一个非常非常小的应用程序上试用它。它实际上是一个静态网站,但我想利用 Angular 的路由来确保所有页面都可以立即加载。所以我的结构是这样的:

my-project
    css
    images
    js
        angular
            app.js
            app.routes.js
            mainCtrl.js
    views
        home.html
        about.html
        contact.html
    index.html

所以我知道这个文件夹结构不是很好,但我只会在这个项目中使用 Angular 进行路由,仅此而已,所以它符合我的需求。

我把<base href="/">放在头上,把ng-appng-controller放在身体里,在身体里的某个地方也放了一个<div ng-view>

我添加了$locationProvider.html5Mode(true) 并试用了该应用程序。然后我的所有脚本都被加载为http://localhost:8888/script.js,这是不正确的。该项目位于一个文件夹中,因此index.html 位于http://localhost:8888/my-project/index.html 中。因此,它应该从http://localhost:8888/my-project/js/angular/app.js 加载脚本。

我对@9​​87654334@ 有什么不明白的地方吗?最终我可能会在某个地方在线托管这个应用程序,所以我希望脚本等的 URL 都与文件真正相关。有人有什么想法吗?

好的,所以在base href 标记上方,我的CSS 样式将链接为css/style.css,在body 标记的底部,我将我的脚本加载为js/init.jsjs/angular/app.js例如。这将尝试加载它,就好像 js 文件夹直接位于 localhost:8888/js 一样。

【问题讨论】:

  • 听起来你需要<base href="/my-project/">
  • base href 不仅是一个角度调用,而且还告诉您所有的相关链接从哪里开始。不过,您的 js 文件的加载位置与您的角度路由没有任何关系。你是如何加载它们的,你把基本 href 放在哪里?
  • 您能否展示您的index.html 文件的示例,尤其是<script> 标签
  • 我更新了我的答案以向您展示@Phil。我知道使用 base href 可以工作,但我认为它应该使所有文件都与该索引文件相关?或者这不完全是如何工作的?例如,如果我要将这个应用程序放到服务器上供全世界查看,我将不得不再次更改 `href="/my-project/"。
  • @germainelol 是的。 <base> 标记将根路径 / URI 设置为所有相对 URI 的基础。如果该路径根据其部署位置发生更改,则需要更改它

标签: javascript angularjs


【解决方案1】:

Angular 框架是一个单页应用程序 (SPA),它能够在浏览器中运行,本质上是欺骗浏览器运行代码 sn-ps,而不是通过使用服务器调用“哈希”(#)页面锚。通常,带有# 的 URL 会跳转到页面中的特定锚点;对于 Angular 或其他类似的 SPA 框架,# 被重定向到代码段。

理想情况下,您不希望在页面 URL 中引用此 #。这就是 Html5Mode 发挥作用的地方。 Html5Mode 能够隐藏 #,通过使用HTML5 Push State(又名历史API)。

启用 Html5Mode 后,页面上的普通链接会被 Angular 以事件监听器静默替换。当这些事件被触发时,当前页面被推送到浏览器历史记录中,并加载新页面。这会给人一种您正在导航到新页面的错觉,甚至允许操作后退按钮。

当您处理从正在运行的应用程序中单击的链接时,这一切都很好,但是如果您从外部源导航到页面,则依赖事件侦听器将无法工作,其中 Angular 未加载到内存中然而。为了解决这个问题,您必须从支持URL rewrites 的网络服务器加载您的页面。当服务器收到对没有物理页面的 URL 的请求时,它会重写 URL 以加载基本 HTML 页面,Angular 可以在其中加载和接管。

当 Angular 收到以这种方式重写的路由请求时,它必须首先确定预期的路由是什么。这就是Base HTML Tag 发挥作用的地方。 Angular 使用 Base 引用来帮助它确定 URL 的哪一部分在服务器上,哪一部分是客户端路由。本质上,如果未启用 Html5Mode,则 URL 中的 # 将位于何处。

不幸的是,Base 是一个 HTML 标签,浏览器使用的不仅仅是 Angular。浏览器还使用此标签来确定使用相对路径加载脚本和资源的正确位置,无论位置栏中的路径如何。通常,如果所有脚本和资源都相对于 Index.html 文件的位置,这不是问题。当Base 被省略时,浏览器将从当前URI 确定的明显 基本路径加载脚本。但是,一旦您提供它,浏览器将使用您提供的任何值。

一般来说,除非您在站点的子页面上托管 Angular,并且您希望您的用户期望 URL 字符串中包含特定内容,否则您应该始终控制服务器上的基础,并使用 Base="/"客户端。

【讨论】:

  • 刚开始阅读它,我没有反对任何东西。无论如何,我遵循了你的逻辑,并申请了base="/project/"。因此,当在应用程序内部时,我的路由工作正常,因为我在 /test 上应用了一个模板,该模板可以正常加载视图。我遇到了您提到的错误,但如果我尝试立即加载 project/test 而不从主页导航到它,那么我会收到 404 not found 错误。您通常如何克服这个问题?
  • @Claies <base> 标签还使浏览器能够加载正确的资源,而不管位置栏中显示的路径如何。否则,相对 URI 会从当前 URI 的 明显 基本路径解析。我没有投反对票,但这可能是您在解释中遗漏的内容
  • 我更新了问题并添加了指向该文章的链接,该文章讨论了如何在各种服务器上设置 URL 重写。
  • @germainelol 如果您使用的是节点,则不需要 apache 代码;那篇文章展示了多种不同 HTTP 服务器类型的技术。
猜你喜欢
  • 2013-11-05
  • 1970-01-01
  • 1970-01-01
  • 2015-08-21
  • 2013-11-06
  • 2015-02-16
  • 2014-09-10
  • 2015-08-20
相关资源
最近更新 更多