通过在AngularJS中启用HTML5模式,$location
服务将重写URL以从中删除hashbang。这是一个很棒的功能,可以帮助我完成我的应用程序,但是它的回退到hashbang模式有一个问题。我的服务需要身份验证,我被迫使用我的应用程序的外部身份验证机制。如果用户尝试使用其中的hashbang转到我的应用的URL,它将首先将它们重定向到身份验证页面(除非成功通过身份验证,否则不会触摸我的服务),然后将它们重定向回我的应用程序。由于哈希标签只能从客户端看到,所以当它们到达我的服务器时,它将会丢失路由的所有部分。一旦对它们进行了身份验证,它们就可以重新输入URL并且它可以正常工作,但它会在一个初始时间内导致用户体验中断。
我的问题是,有没有办法从$location.html5Mode(true)
转到不支持浏览器的整页重新加载的后备,在AngularJS中完全跳过hashbang路由方法?
我正在瞄准的可用实现的最佳比较将是诸如在github.com上浏览文件夹之类的东西。如果浏览器支持在不启动页面刷新的情况下重写URL,则页面将异步加载必要的部分。如果浏览器不支持,则当用户单击文件夹时,将发生整页刷新。用AngularJS代替使用hashbang模式可以实现吗?
答案 0 :(得分:2)
请勿覆盖核心功能。
使用Modernizr,进行特征检测,然后相应地进行。
检查历史记录API支持
if (Modernizr.history) {
// history management works!
} else {
// no history support :(
// fall back to a scripted solution like History.js
}
答案 1 :(得分:1)
尝试在浏览器的HTML5 History API检查中包装$ location和$ routeProvider配置,如下所示:
if (isBrowserSupportsHistoryAPI()) {
$location.html5Mode(true)
$routeProvider.when(...);
}
如果您使用它来更改路径,也可能需要为$ location创建一个包装器。 (抱歉可怕的英语)
答案 2 :(得分:1)
为什么不在这种情况下处理客户端上未经过身份验证的重定向?我需要更多地了解您的应用程序如何工作以为您提供更具体的解决方案,但基本上类似于:
当AngularJS应用程序启动时,您可以在模块的运行块中找到一些东西:
module('app',[])
.configure(...yadda...yadda...yadda...)
.run(['$location', 'authenticationService', function($location, auth) {
if (!auth.isAuthenticated()) {
$location.url(authenticationUrl)
}
});
我已经接受了一项服务,该服务会发现您是否以某种方式进行了身份验证,由您决定是否可以检查会话cookie,这可能是您要求的API。实际上取决于您希望在客户端应用程序运行时继续检查身份验证的方式。
答案 3 :(得分:1)
您可以尝试覆盖$ location服务的功能。一般的想法是根据某人是否已经过身份验证来重写URL,或者只是对所有URL使用单一方法(没有hashbang),无论html5mode是否打开。
我不确定我是否完全理解用例,因此无法编写您需要的确切代码。以下是如何覆盖/实现和注册$ location服务的示例实现,只需确保hashbang 始终消除:
app.service('$location', [function() {
var DEFAULT_PORTS = {
ftp: 21,
http: 80,
https: 443
};
angular.extend(this, {
absUrl: function() {
return location.href;
},
hash: function(hash) {
return location.hash.substr(1);
},
host: function() {
return location.host;
},
path: function(path) {
if (!path) {
return location.pathname;
}
location.pathname = path;
return this;
},
port: function() {
return location.port ? Number(location.port) : DEFAULT_PORTS[this.protocol()] || null;
},
protocol: function() {
return location.protocol.substr(0, location.protocol.length - 1);
},
replace: function() {
return this;
},
search: function(search, paramValue) {
if (search || paramValue) {
return this;
}
var query = {};
location.search.substr(1).split("&").forEach(function(pair) {
pair = pair.split("="); query[pair[0]] = decodeURIComponent(pair[1]);
});
return query;
},
url: function(url, replace) {
return this.path();
}
});
}]);