$location/在 html5和 hashbang 模式/链接重写之间切换

我的印象是,Angular 会重写出现在 tempaltes 中锚标记的 href 属性中的 URL,这样它们就可以在 html5模式或 hashbang 模式下工作。定位服务的文档似乎说 HTML 链接重写处理了 hashbang 的情况。因此,我希望当不处于 HTML5模式时,会插入散列,而在 HTML5模式下,则不会。

然而,似乎没有重写正在发生。下面的示例不允许我仅仅更改模式。应用程序中的所有链接都需要手工重写(或者在运行时从变量派生)。是否需要根据模式手动重写所有 URL?

我没有看到在 Angular 1.0.6、1.1.4或1.1.3中进行任何客户端 URL 重写。似乎所有 href 值都需要在 #/for hashbang mode 和/for html5 mode 前面加上 #/。

是否有一些必要的配置导致重写? 我是否读错了文档? 还是做了其他愚蠢的事情?

举个小例子:

<head>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.3/angular.js"></script>
</head>


<body>
<div ng-view></div>
<script>
angular.module('sample', [])
.config(
['$routeProvider', '$locationProvider',
function ($routeProvider, $locationProvider) {


//commenting out this line (switching to hashbang mode) breaks the app
//-- unless # is added to the templates
$locationProvider.html5Mode(true);


$routeProvider.when('/', {
template: 'this is home. go to <a href="/about"/>about</a>'
});
$routeProvider.when('/about', {
template: 'this is about. go to <a href="/"/>home</a'
});
}
])
.run();
</script>
</body>

附录: 在重读我的问题时,我发现我使用了“重写”这个术语,但是对于我想要重写的人和时间没有充分的清晰度。问题是如何让 角度在呈现路径时重写 URL,以及如何让它跨两种模式统一地解释 JS 代码中的路径。它是关于如何使 Web 服务器做 HTML5兼容的请求重写的 没有

174895 次浏览

有关 AngularJS 路由的文档不是很清楚。它讨论了 Hashbang 和 HTML5模式。事实上,AngularJS 路由有三种模式:

  • Hashbang Mode
  • HTML5模式
  • HTML5模式下的 Hashbang

对于每种模式,都有一个相应的 LocationUrl 类(LocationHashbang Url、 LocationUrl 和 LocationHashbang InHTML5Url)。

为了模拟 URL 重写,您必须将 html5mode 设置为 true,并将 $sniff 类装饰如下:

$provide.decorator('$sniffer', function($delegate) {
$delegate.history = false;
return $delegate;
});

我现在将更详细地解释这一点:

Hashbang Mode

配置:

$routeProvider
.when('/path', {
templateUrl: 'path.html',
});
$locationProvider
.html5Mode(false)
.hashPrefix('!');

如果需要在 HTML 文件中使用带哈希的 URL,例如

<a href="index.html#!/path">link</a>

在浏览器中,您必须使用以下链接: http://www.example.com/base/index.html#!/base/path

正如您在纯 Hashbang 模式中看到的那样,HTML 文件中的所有链接都必须以“ index.HTML # !”.

HTML5模式

配置:

$routeProvider
.when('/path', {
templateUrl: 'path.html',
});
$locationProvider
.html5Mode(true);

您应该在 HTML-file 中设置基础

<html>
<head>
<base href="/">
</head>
</html>

在这种模式下,可以在 HTML 文件中使用不带 # 的链接

<a href="/path">link</a>

浏览器中的链接:

http://www.example.com/base/path

HTML5模式下的 Hashbang

当我们实际使用 HTML5模式但是在不兼容的浏览器中时,这种模式会被激活。我们可以在兼容的浏览器中模拟这种模式,方法是修饰 $sniff 服务并将历史记录设置为 false。

配置:

$provide.decorator('$sniffer', function($delegate) {
$delegate.history = false;
return $delegate;
});
$routeProvider
.when('/path', {
templateUrl: 'path.html',
});
$locationProvider
.html5Mode(true)
.hashPrefix('!');

在 HTML-file 中设置基础:

<html>
<head>
<base href="/">
</head>
</html>

在这种情况下,也可以不使用 HTML 文件中的散列来编写链接

<a href="/path">link</a>

浏览器中的链接:

http://www.example.com/index.html#!/base/path

我希望能够使用 HTML5模式和一个固定的令牌访问我的应用程序,然后切换到 hashbang 方法(保留令牌,以便用户可以刷新他的页面)。

访问我的应用程序的 URL:

http://myapp.com/amazing_url?token=super_token

然后,当用户加载页面时:

http://myapp.com/amazing_url?token=super_token#/amazing_url

然后当用户导航时:

http://myapp.com/amazing_url?token=super_token#/another_url

通过这种方式,我将令牌保存在 URL 中,并在用户浏览时保持状态。我丢失了一些 URL 的可见性,但是没有完美的方法来做到这一点。

所以不要启用 HTML5模式,然后添加这个控制器:

.config ($stateProvider)->
$stateProvider.state('home-loading', {
url: '/',
controller: 'homeController'
})
.controller 'homeController', ($state, $location)->
if window.location.pathname != '/'
$location.url(window.location.pathname+window.location.search).replace()
else
$state.go('home', {}, { location: 'replace' })

这花了我一段时间来弄清楚,所以这是我如何得到它的工作-角 WebAPI ASP 路由没有 # 为 SEO

  1. 添加到 Index.html-base href = “/”>
  2. 将 $locationProvider.html5Mode (true) ; 添加到 app.config

  3. 我需要在上传图像时忽略某个控制器(在主控制器中) ,因此我将该规则添加到 RouteConfig

         routes.MapRoute(
    name: "Default2",
    url: "Home/{*.}",
    defaults: new { controller = "Home", action = "SaveImage" }
    );
    
  4. In Global.asax add the following - making sure to ignore api and image upload paths let them function as normal otherwise reroute everything else.

     private const string ROOT_DOCUMENT = "/Index.html";
    
    
    protected void Application_BeginRequest(Object sender, EventArgs e)
    {
    var path = Request.Url.AbsolutePath;
    var isApi = path.StartsWith("/api", StringComparison.InvariantCultureIgnoreCase);
    var isImageUpload = path.StartsWith("/home", StringComparison.InvariantCultureIgnoreCase);
    
    
    if (isApi || isImageUpload)
    return;
    
    
    string url = Request.Url.LocalPath;
    if (!System.IO.File.Exists(Context.Server.MapPath(url)))
    Context.RewritePath(ROOT_DOCUMENT);
    }
    
  5. Make sure to use $location.url('/XXX') and not window.location ... to redirect

  6. Reference the CSS files with absolute path

and not

<link href="app/content/bootstrapwc.css" rel="stylesheet" />

最后说明-这样做给了我完全的控制权,我不需要做任何网络配置。

希望这个能帮上忙,因为我花了很长时间才弄明白。

未来的毛皮阅读器,如果你使用 角度1.6,你也需要改变 hashPrefix:

appModule.config(['$locationProvider', function($locationProvider) {
$locationProvider.html5Mode(true);
$locationProvider.hashPrefix('');
}]);

不要忘记在 HTML <head>中设置基础:

<head>
<base href="/">
...
</head>

关于更改日志 here的更多信息。