没有哈希'#'的AngularJS路由


223

我正在学习AngularJS,有一件事让我很烦。

我用来$routeProvider为我的应用程序声明路由规则:

$routeProvider.when('/test', {
  controller: TestCtrl,
  templateUrl: 'views/test.html'
})
.otherwise({ redirectTo: '/test' });

但是当我在浏览器中导航到我的应用程序时,我看到的app/#/test不是app/test

所以我的问题是为什么AngularJS将此哈希添加#到url中?有可能避免它吗?


2
如果您使用的是Angular 1.6,这是解决方案
Mistalis

Answers:


265

实际上,对于非HTML5浏览器,您需要#(#标签)。

否则,他们将只通过提到的href对服务器进行HTTP调用。#是一个旧的浏览器短路问题,它不会触发请求,它允许许多js框架在此之上构建自己的客户端重新路由。

您可以$locationProvider.html5Mode(true)用来告诉angular使用HTML5策略(如果有)。

以下是支持HTML5策略的浏览器列表:http : //caniuse.com/#feat=history


4
好的谢谢。这是我所怀疑的。但是对于我来说,这是非常用户不友好的!假设我希望通过url,app / res提供一些资源。我的网站用户如何才能发现他们应该输入app /#/ res呢?
pikkvile 2013年

5
但是,如果是这样,为什么我需要这些路径在位置栏中可见?如果用户不使用它们,我可以制作单页javascript应用程序。
2013年

6
当您要跟踪应用程序状态时,这很有用。框架提供了历史机制。另外,它允许直接访问通过URL共享,例如你的应用程序的状态
加功能

6
在支持HTML5历史记录API的现代浏览器中,不需要标签。请参阅@skeep的答案和提供的链接。在HTML5模式下,只有浏览器不支持Angular,它才会使用#标签。另请注意,如果您不想使用$ routeProvider,则可以使用ng-clicks和ng-include来连接自己的路由(实际上,如果需要多个级别的路由,则必须这样做)路由,因为ng-view每页只能出现一次)。另请参见stackoverflow.com/questions/12793609/...
马克Rajcok

2
对于hashbang / pushstate /服务器端渲染html案例,Twitter很好阅读engineering.twitter.com/2012/12/…解释了他们如何做到这一点,因此它与旧浏览器和搜索向后兼容引擎。我知道它不是特定于angularjs的,但是您可以重现该流程。
jackdbernier

47

如果您像其他人一样启用了html5mode,并创建一个.htaccess包含以下内容的文件(根据您的需要进行调整):

RewriteEngine   On
RewriteBase     /
RewriteCond     %{REQUEST_URI} !^(/index\.php|/img|/js|/css|/robots\.txt|/favicon\.ico)
RewriteCond     %{REQUEST_FILENAME} !-f
RewriteCond     %{REQUEST_FILENAME} !-d
RewriteRule     ./index.html [L]

输入正确的路线后,用户将被定向到您的应用程序,您的应用程序将读取该路线并将其带​​到其中的正确“页面”。

编辑:只需确保没有任何文件或目录名称与您的路由冲突。


有这个的Nginx版本吗?当我加载/about页面失败,除非我通过应用程序进入页面。
chovy

从未使用过它们,但请尝试以下操作:stackoverflow.com/questions/5840497/convert-htaccess-to-nginx
bearfriend 2013年

3
@chovy-nGinx版本:服务器{server_name my-app; 根/ path / to / app; 位置/ {try_files $ uri $ uri / /index.html; }
穆恩·海达尔

4
记住头部标签中的<base href =“ /”> </ base>
Silvio Troia 2014年

谢谢!没有这个,就不可能进行深层链接。如果您需要深层链接,我仍然不确定维护它的美观性或URI是否值得,特别是在某些云/ paas环境中,如果您可能无法轻松访问httpd config,则值得维护。
皮埃尔·亨利

39

让我们写出看起来简单而简短的答案

在路由器的末尾添加html5Mode(true)

app.config(function($routeProvider,$locationProvider) {

    $routeProvider.when('/home', {
        templateUrl:'/html/home.html'
    });

    $locationProvider.html5Mode(true);
})

在html头中添加基本标记

<html>
<head>
    <meta charset="utf-8">    
    <base href="/">
</head>

感谢@plus-详细说明以上答案


我一直无法使它正常工作。我已经在我的特定详细信息上发布了一个新问题,该问题的详细信息为:stackoverflow.com/questions/36041074/…请查看此信息,如果您能提供帮助,我将不胜感激。
拉里·马爹利

30

尝试

$locationProvider.html5Mode(true)

$ locationProvider上的 更多信息
使用$ location


6
对不起,我加入的.config(函数($ locationProvider){$ locationProvider.html5Mode(真)}),但我得到的index.html#%2Fhome没有的index.html /家
zloctb

12

以下信息来自:https :
//scotch.io/quick-tips/pretty-urls-in-angularjs-removing-the-hashtag

获取干净的URL并从Angular中的URL中删除主题标签非常容易。
默认情况下,AngularJS将路由带有井号的URL例如:

有两件事要做。

  • 配置$ locationProvider

  • 为相对链接奠定基础

  • $定位服务

在Angular中,$ location服务解析地址栏中的URL,并对应用程序进行更改,反之亦然。

我强烈建议您阅读Angular的$ location官方文档,以便对定位服务及其提供的功能有所了解。

https://docs.angularjs.org/api/ng/service/$location

$ locationProvider和html5Mode

  • 我们将使用$ locationProvider模块并将html5Mode设置为true。
  • 我们将在定义Angular应用程序并配置路线时执行此操作。

    angular.module('noHash', [])
    
    .config(function($routeProvider, $locationProvider) {
    
       $routeProvider
           .when('/', {
               templateUrl : 'partials/home.html',
               controller : mainController
           })
           .when('/about', {
               templateUrl : 'partials/about.html',
               controller : mainController
           })
           .when('/contact', {
               templateUrl : 'partials/contact.html',
               controller : mainController
           });
    
       // use the HTML5 History API
       $locationProvider.html5Mode(true); });

什么是HTML5历史记录API?这是使用脚本来操纵浏览器历史记录的标准化方法。这使Angular可以更改页面的路由和URL,而无需刷新页面。有关此的更多信息,这是一篇不错的HTML5 History API文章:

http://diveintohtml5.info/history.html

设置相对链接

  • 要使用相对链接来链接应用程序,您需要<base><head>文档中设置。这可能在Angular应用程序的根index.html文件中。找到<base>标签,并将其设置为您要为应用程序使用的根URL。

例如: <base href="https://stackoverflow.com/">

  • 还有许多其他方法可以配置此设置,并且将HTML5模式设置为true可以自动解析相对链接。如果您的应用程序的根目录与url不同(例如/ my-base),则将其用作基础。

旧版浏览器的后备

  • 对于不支持HTML5历史记录API的浏览器,$ location服务将自动回退为hashbang方法。
  • 这对您是透明的,您无需进行任何配置即可工作。从Angular $ location文档中,您可以看到fallback方法及其工作方式。

结论

  • 这是获取漂亮的URL并在Angular应用程序中删除主题标签的简单方法。玩那些超级干净,超级快速的Angular应用程序,玩得开心!

3

如果要在使用Apache的Angular服务的OS X 10.8上进行本地配置,则可以在.htaccess文件中找到以下内容:

<IfModule mod_rewrite.c>
    Options +FollowSymlinks
    RewriteEngine On
    RewriteBase /~yourusername/appname/public/
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} !.*\.(css|js|html|png|jpg|jpeg|gif|txt)
    RewriteRule (.*) index.html [L]
</IfModule>

如果未设置选项+ FollowSymlinks,则可能会在日志中给您一个禁止的错误,如下所示:

Options FollowSymLinks or SymLinksIfOwnerMatch is off which implies that RewriteRule directive is forbidden

需要重写基础,否则请求将解析到您的服务器根目录,除非您专门配置了虚拟主机,否则默认情况下本地目录不是您的项目目录,因此您需要设置路径,以便请求找到您的项目根目录。例如,在我的机器上,我有一个/ Users / me / Sites目录,其中存放了所有项目。就像旧的OS X设置一样。

接下来的两行有效地说明了该路径不是目录还是文件,因此您需要确保没有与应用程序路由路径相同的文件或目录。

下一个条件是,如果请求未以指定的文件扩展名结尾,则在此处添加所需内容

[L]最后一​​个是说要为index.html文件提供服务-您的应用程序可以处理所有其他请求。

如果仍然有问题,请检查apache日志,它可能会为您提供有用的提示:

/private/var/log/apache2/error_log

如果将MAMP用作本地Apache服务器,请确保第一个RewriteBase是相对链接。例如RewriteBase / angularjs_site_folder /
大卫·道格拉斯

3

使用HTML5模式需要在服务器端重写URL,基本上,您必须重写所有指向应用程序入口点的链接(例如index.html)。<base>在这种情况下,要求标记也很重要,因为它使AngularJS可以区分url的一部分(作为应用程序的基础)和应由应用程序处理的路径。有关更多信息,请参阅《AngularJS开发人员指南-使用$ location HTML5模式服务器端》


更新资料

如何:配置服务器以使用html5Mode 1

启用html5Mode后,该#字符将不再在您的网址中使用。该#符号很有用,因为它不需要服务器端配置。不使用#,URL看起来会更好,但是它也需要服务器端重写。这里有些例子:

Apache重写

<VirtualHost *:80>
    ServerName my-app

    DocumentRoot /path/to/app

    <Directory /path/to/app>
        RewriteEngine on

        # Don't rewrite files or directories
        RewriteCond %{REQUEST_FILENAME} -f [OR]
        RewriteCond %{REQUEST_FILENAME} -d
        RewriteRule ^ - [L]

        # Rewrite everything else to index.html to allow html5 state links
        RewriteRule ^ index.html [L]
    </Directory>
</VirtualHost>

Nginx重写

server {
    server_name my-app;

    index index.html;

    root /path/to/app;

    location / {
        try_files $uri $uri/ /index.html;
    }
}

Azure IIS重写

<system.webServer>
  <rewrite>
    <rules> 
      <rule name="Main Rule" stopProcessing="true">
        <match url=".*" />
        <conditions logicalGrouping="MatchAll">
          <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
          <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        </conditions>
        <action type="Rewrite" url="/" />
      </rule>
    </rules>
  </rewrite>
</system.webServer>

快速重写

var express = require('express');
var app = express();

app.use('/js', express.static(__dirname + '/js'));
app.use('/dist', express.static(__dirname + '/../dist'));
app.use('/css', express.static(__dirname + '/css'));
app.use('/partials', express.static(__dirname + '/partials'));

app.all('/*', function(req, res, next) {
    // Just send the index.html for other files to support HTML5Mode
    res.sendFile('index.html', { root: __dirname });
});

app.listen(3006); //the port you want to use

也可以看看


1

在Angular 6中,通过路由器可以使用:

RouterModule.forRoot(routes, { useHash: false })

0

您还可以使用以下代码重定向到主页(主页):

{ path: '', redirectTo: 'home', pathMatch: 'full'}

在如上所述指定重定向之后,您可以重定向其他页面,例如:

{ path: 'add-new-registration', component: AddNewRegistrationComponent},
{ path: 'view-registration', component: ViewRegistrationComponent},
{ path: 'home', component: HomeComponent}

0

**

建议在Angular中使用HTML 5样式(PathLocationStrategy)作为定位策略

** 因为

  1. 它会生成干净且SEO友好的URL,使用户更易于理解和记住。
  2. 您可以利用服务器端呈现的优势,这可以通过在服务器交付客户端之前首先呈现服务器中的页面来加快我们的应用程序的加载速度。

仅在必须支持旧版浏览器时才使用Hashlocationstrtegy。

点击这里了解更多

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.