我的印象是Angular会重写在tempaltes中的锚标记的href属性中出现的URL,这样无论是在html5模式还是hashbang模式下它们都能正常工作。 documentation for the location service似乎表示HTML链接重写可以解决hashbang情况。因此,我希望当不在HTML5模式下时,会插入哈希值,而在HTML5模式下,它们则不会。
然而,似乎没有重写。以下示例不允许我只更改模式。应用程序中的所有链接都需要手动重写(或者在运行时从变量派生。我是否需要根据模式手动重写所有URL?
我没有在Angular 1.0.6,1.1.4或1.1.3中看到任何客户端网址重写。似乎所有href值都需要以#/为hashbang模式和/为html5模式。
是否需要一些配置才能导致重写?我误读了文档吗?做些别傻话?
这是一个小例子:
<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>
附录:在重新阅读我的问题时,我发现我使用了“重写”一词,但没有明确说明我何时以及何时进行重写。问题是如何让 Angular 在呈现路径时重写URL,以及如何在两种模式下统一解释JS代码中的路径。关于如何使Web服务器与请求进行HTML5兼容的重写, 。
答案 0 :(得分:357)
关于AngularJS路由的文档不是很清楚。它讨论了Hashbang和HTML5模式。事实上,AngularJS路由以三种模式运行:
对于每种模式,都有一个相应的LocationUrl类(LocationHashbangUrl,LocationUrl和LocationHashbangInHTML5Url)。
为了模拟URL重写,你必须实际将html5mode设置为true并按如下方式装饰$ sniffer类:
$provide.decorator('$sniffer', function($delegate) {
$delegate.history = false;
return $delegate;
});
我现在将更详细地解释这一点:
配置:
$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#!”。
配置:
$routeProvider
.when('/path', {
templateUrl: 'path.html',
});
$locationProvider
.html5Mode(true);
您应该在HTML文件中设置基础
<html>
<head>
<base href="/">
</head>
</html>
在此模式下,您可以使用不包含HTML文件中的#的链接
<a href="/path">link</a>
浏览器中的链接:
http://www.example.com/base/path
当我们实际使用HTML5模式但在不兼容的浏览器中时,此模式被激活。我们可以通过修改$ sniffer服务并将历史记录设置为false来在兼容的浏览器中模拟此模式。
配置:
$provide.decorator('$sniffer', function($delegate) {
$delegate.history = false;
return $delegate;
});
$routeProvider
.when('/path', {
templateUrl: 'path.html',
});
$locationProvider
.html5Mode(true)
.hashPrefix('!');
在HTML文件中设置基础:
<html>
<head>
<base href="/">
</head>
</html>
在这种情况下,也可以在HTML文件中没有哈希的情况下编写链接
<a href="/path">link</a>
浏览器中的链接:
http://www.example.com/index.html#!/base/path
答案 1 :(得分:7)
对于未来的读者,如果您使用 Angular 1.6 ,您还需要更改hashPrefix
:
appModule.config(['$locationProvider', function($locationProvider) {
$locationProvider.html5Mode(true);
$locationProvider.hashPrefix('');
}]);
不要忘记在HTML <head>
中设置基础:
<head>
<base href="/">
...
</head>
有关更改日志的更多信息 here 。
答案 2 :(得分:0)
我希望能够使用HTML5模式和固定令牌访问我的应用程序,然后切换到hashbang方法(保留令牌,以便用户可以刷新他的页面)。
访问我的应用的网址:
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' })
答案 3 :(得分:0)
这花了我一段时间才弄明白所以这就是我如何工作 - 没有#for SEO的Angular WebAPI ASP路由
添加$ locationProvider.html5Mode(true);到app.config
我需要在上传图片时忽略某个控制器(位于家庭控制器中),所以我将该规则添加到RouteConfig
routes.MapRoute(
name: "Default2",
url: "Home/{*.}",
defaults: new { controller = "Home", action = "SaveImage" }
);
在Global.asax中添加以下内容 - 确保忽略api和图像上传路径,让它们正常运行,否则重新路由其他所有内容。
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);
}
请务必使用$ location.url('/ XXX')而非window.location ...重定向
引用具有绝对路径的CSS文件
而不是
<link href="app/content/bootstrapwc.css" rel="stylesheet" />
最后的注意事项 - 这样做可以让我完全控制,我不需要对网络配置做任何事情。
希望这会有所帮助,因为这花了我一段时间才弄明白。