AngularJS HTML5模式降级为全页面重载,以代替hashbang



通过在AngularJS中启用HTML5模式,$location服务将重写URL以删除其中的hashbang。这是一个很好的功能,可以帮助我使用我的应用程序,但它回退到hashbang模式时出现了问题。我的服务需要身份验证,我被迫使用应用程序中的外部身份验证机制。如果用户试图访问我的应用程序的URL并在其中添加hashbang,它会首先将他们重定向到身份验证页面(除非成功进行身份验证,否则永远不会接触我的服务),然后将他们重定向回我的应用程序。由于散列标签只能从客户端看到,所以当它们到达我的服务器时,它会丢弃路由的任何部分。一旦他们通过了身份验证,他们可能会重新输入URL,它会起作用,但最初的一次会对用户体验造成干扰。

那么,我的问题是,从$location.html5Mode(true)到不支持的浏览器的全页面重载的回退,是否有任何方法可以跳过完全在AngularJS中路由的hashbang方法?

我的目标的可用实现的最佳比较是在github.com上浏览文件夹。如果浏览器支持在不启动页面刷新的情况下重写URL,则页面将异步加载必要的部分。如果浏览器不支持它,则当用户单击文件夹时,会进行整页刷新。这可以用AngularJS代替hashbang模式实现吗?

不要覆盖核心功能。

使用Modernizr,进行特征检测,然后进行相应的操作。

检查历史API支持

if (Modernizr.history) {
  // history management works!
} else {
  // no history support :(
  // fall back to a scripted solution like History.js
}

尝试在浏览器的HTML5历史API检查中包装$location和$routeProvider配置,如下所示:

if (isBrowserSupportsHistoryAPI()) {
    $location.html5Mode(true)
    $routeProvider.when(...);
}

如果您使用$location来更改路径,还可能需要创建一个包装器。(抱歉英语不好)

在这种情况下,为什么不在客户端处理未经身份验证的重定向?我需要更多地了解你的应用程序是如何工作的,才能给你一个更具体的解决方案,但本质上是这样的:

  1. 用户转到AngularJS处理的路由,服务器提供AngularJS主模板和javascript
  2. 用户未通过身份验证,AngularJS检测到这一点并重定向到身份验证页面

当AngularJS应用程序启动时,模块的运行块中可能有一些内容:

module('app',[])
  .configure(...yadda...yadda...yadda...)
  .run(['$location', 'authenticationService', function($location, auth) {
    if (!auth.isAuthenticated()) {
      $location.url(authenticationUrl) 
    }
  });

我已经加入了一个服务,它会发现你是否以某种方式通过了身份验证,取决于你如何,可以检查会话cookie,可以点击你的API询问。这实际上取决于您希望在客户端应用程序运行时如何继续检查身份验证。

您可以尝试覆盖$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();
        }
    });
}]);

最新更新