AngularJS HTML5模式降级为完整页面重新加载,以代替hashbang

AngularJS HTML5模式降级为完整页面重新加载,以代替hashbang,angularjs,Angularjs,通过在AngularJS中启用HTML5模式,$location服务将重写URL以删除其中的hashbang。这是一个很好的特性,可以帮助我使用我的应用程序,但是它的回退到hashbang模式有一个问题。我的服务需要身份验证,我被迫从应用程序使用外部身份验证机制。如果用户试图转到包含hashbang的我的应用程序的URL,它将首先将他们重定向到身份验证页面(除非成功验证,否则永远不会接触我的服务),然后将他们重定向回我的应用程序。由于散列标记只能从客户端看到,所以当路由到达我的服务器时,它将从路

通过在AngularJS中启用HTML5模式,
$location
服务将重写URL以删除其中的hashbang。这是一个很好的特性,可以帮助我使用我的应用程序,但是它的回退到hashbang模式有一个问题。我的服务需要身份验证,我被迫从应用程序使用外部身份验证机制。如果用户试图转到包含hashbang的我的应用程序的URL,它将首先将他们重定向到身份验证页面(除非成功验证,否则永远不会接触我的服务),然后将他们重定向回我的应用程序。由于散列标记只能从客户端看到,所以当路由到达我的服务器时,它将从路由的任何部分脱落。一旦他们通过身份验证,他们可能会重新输入URL,它就会工作,但这是一个初始时间,将导致用户体验中断

那么,我的问题是,有没有办法从
$location.html5Mode(true)
过渡到对不支持的浏览器重新加载整个页面,从而完全跳过AngularJS中的hashbang路由方法


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

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

if (isBrowserSupportsHistoryAPI()) {
    $location.html5Mode(true)
    $routeProvider.when(...);
}
如果使用$location更改路径,还可能需要创建$location的包装。
(抱歉,英语太糟糕了)

对于这种情况,为什么不在客户端处理未经身份验证的重定向?我需要更多地了解你的应用程序是如何工作的,以便为你提供更具体的解决方案,但本质上类似于:

  • 用户转到AngularJS处理的路由,服务器提供AngularJS主模板和javascript
  • 用户未通过身份验证,AngularJS检测到此情况并重定向到身份验证页面
  • 当AngularJS应用程序启动时,模块的run块中可能有一些内容:

    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();
            }
        });
    }]);
    

    不要覆盖核心功能

    使用Modernizer,进行特征检测,然后进行相应的处理

    检查历史API支持情况

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

    你有没有想出解决这个问题的办法?我面临着类似的情况。