$ location / html5和hashbang模式/链接重写之间的切换
我的印象是,Angular会重写出现在临时标签内的锚标签的href属性中的URL,使得它们可以在html5模式或hashbang模式下工作。 位置服务的文档似乎说HTML链接重写照顾的hashbang的情况。 因此,我期望在不使用HTML5模式时,插入哈希值,而在HTML5模式下,则不会。
但是,似乎没有重写正在发生。 下面的例子不允许我改变模式。 应用程序中的所有链接都需要手动重写(或者在运行时从variables派生出来)。我是否需要根据模式手动重写所有URL?
我没有看到在Angular 1.0.6,1.1.4或1.1.3中有任何客户端的URL重写。 似乎所有的href值都需要用#/作为hashbang模式和/ html5模式。
是否有一些configuration需要重写? 我误解了文档吗? 做别的事情傻吗?
这是一个小例子:
<head> <script src="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在渲染path时重写URL,以及如何在两种模式下统一解释JS代码中的path。 这不是关于如何使Web服务器执行与HTML5兼容的重写请求。
关于AngularJS路由的文档不是很清楚。 它谈到Hashbang和HTML5模式。 事实上,AngularJS路由有三种模式:
- 哈希邦模式
- HTML5模式
- 在HTML5模式下的Hashbang
对于每种模式,都有一个相应的LocationUrl类(LocationHashbangUrl,LocationUrl和LocationHashbangInHTML5Url)。
为了模拟URL重写,你必须实际设置html5mode为true,并装饰$嗅探器类如下:
$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
: http://www.example.com/base/index.html#!/base/path
base/ http://www.example.com/base/index.html#!/base/path
正如你所看到的,在纯粹的Hashbang模式下,HTML文件中的所有链接都必须以“index.html#!”为底。
HTML5模式
组态:
$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模式下的Hashbang
当我们实际使用HTML5模式,但在不兼容的浏览器中时,此模式被激活。 我们可以通过装饰$嗅探器服务并将历史logging设置为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
裘皮未来的读者,如果你使用的是Angular 1.6 ,你还需要更改hashPrefix
:
appModule.config(['$locationProvider', function($locationProvider) { $locationProvider.html5Mode(true); $locationProvider.hashPrefix(''); }]);
不要忘记在你的HTML <head>
设置基础:
<head> <base href="/"> ... </head>
有关更新日志的更多信息
这花了我一段时间弄清楚,所以这就是我如何得到它的工作 – Angular WebAPI ASP路由没有#为SEO
- 添加到Index.html – base href =“/”>
-
添加$ locationProvider.html5Mode(true); 到app.config
-
我需要一个特定的控制器(这是在家里的控制器)被忽略的上传图像,所以我把这个规则添加到RouteConfig
routes.MapRoute( name: "Default2", url: "Home/{*.}", defaults: new { controller = "Home", action = "SaveImage" } );
-
在Global.asax中添加以下内容 – 确保忽略api和图像上传path,让它们正常工作,否则重新路由其他所有内容。
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 …来redirect
-
使用绝对path引用CSS文件
并不是
<link href="app/content/bootstrapwc.css" rel="stylesheet" />
最后的注意事项 – 这样做给了我完全的控制,我不需要做任何事情的networkingconfiguration。
希望这有帮助,因为这花了我一段时间弄清楚。
我希望能够使用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' })