使用window.location禁用UI-Router交互

时间:2023-01-16 15:15:57

This is a long shot, but UI-router is so popular, thought maybe someone here would have insight on this issue.

这是一个很长的镜头,但UI路由器是如此受欢迎,以为可能有人在这里可以洞察这个问题。

I'm migrating a project to Angular JS. The project consists of a page with several different panels - each of which is downloaded from the server as HTML with AJAX, injected into the page with Javascript, and associated with its own href, which managed by jQuery History.

我正在将项目迁移到Angular JS。该项目由一个包含多个不同面板的页面组成 - 每个面板都是从服务器下载的,带有AJAX的HTML,使用Javascript注入到页面中,并与jQuery History管理的自己的href相关联。

jQuery history tracked the browser states and updated the window.href accordingly after each panel was injected with Javascript. For instance:

jQuery历史跟踪浏览器状态并在每个面板注入Javascript后相应地更新window.href。例如:

Panel 1:
  window.location.href // http://myapp.com/panel1
  History.getLocationHref() // http://myapp.com/panel1
  History.getPageUrl() // http://myapp.com/panel1
Panel 2:
  window.location.href // http://myapp.com/panel2
  History.getLocationHref() // http://myapp.com/panel2
  History.getPageUrl() // http://myapp.com/panel2
Panel 3:
  window.location.href // http://myapp.com/panel3
  History.getLocationHref() // http://myapp.com/panel3
  History.getPageUrl() // http://myapp.com/panel3

etc, etc.

Because each of these panels are injected, rather than compiling them with Angular after injection into the DOM, I'm bootstrapping separate AngularJs Apps for each of them. This has worked fine up until now.

因为每个面板都是注入的,而不是在注入DOM后用Angular编译它们,所以我为每个面板引导了单独的AngularJs应用程序。到目前为止,这已经很好了。

Now I'm using AngularJs UI-router in Panel 2 - so I can render data in alternative templates. The problem is, UI-Router must somehow mess with browser history and/or window href. Because once that app is instantiated, let's say I start at Panel 1, then click Panel 2, then click Panel 3, I have this problem:

现在我在Panel 2中使用AngularJs UI-router - 所以我可以在替代模板中呈现数据。问题是,UI-Router必须以某种方式混淆浏览器历史记录和/或窗口href。因为一旦该应用程序被实例化,让我说我从Panel 1开始,然后单击Panel 2,然后单击Panel 3,我有这个问题:

Panel 1:
  window.location.href // http://myapp.com/panel1
  History.getLocationHref() // http://myapp.com/panel1
  History.getPageUrl() // http://myapp.com/panel1
Panel 2:
  window.location.href // http://myapp.com/panel2
  History.getLocationHref() // http://myapp.com/panel2
  History.getPageUrl() // http://myapp.com/panel2
Panel 3:
  window.location.href // http://myapp.com/panel2
  History.getLocationHref() // http://myapp.com/panel2
  History.getPageUrl() // http://myapp.com/panel3

basically, once UI-Router is instantiated with an app, jQuery History no longer works, and the location href persists at the URL of the ui-router app.

基本上,一旦UI-Router用app实例化,jQuery History就不再有效,并且位置href仍然存在于ui-router应用程序的URL中。

Is there anything I can do to disable ui-router's interaction with the window's location href? Or is integral to how the module works?

我可以做些什么来禁用ui-router与窗口位置href的交互?或者是模块如何工作不可或缺的一部分?

Here's my panel2.states.js file if it helps:

这是我的panel2.states.js文件,如果它有帮助:

angular.module("panel2")
.config(["$stateProvider", function($stateProvider) {
  $stateProvider
    .state('table', {
      views: {
        index: {
 //             controller: "TableController as at",
            templateUrl: "table.html"
        }
      }
    })
    .state('tiles', {
      views: {
        index: {
//              controller: "TilesController as tc",
            templateUrl: "tiles.html"
        }
      }
    });
}]);

Update (4/27/2015)

I solved my particular issue by just getting rid of jQuery History and the features it adds beyond what we need. Instead I just interact directly with window.history:

我解决了我的特殊问题,只是摆脱了jQuery History以及它增加的功能,超出了我们的需要。相反,我只是直接与window.history交互:

 window.history.pushState({panel: "panel3"}, 
    document.title + " | " + 'panel3', 
    window.location.href + "/panel3");

I'm still curious as to what was causing this interaction and if angular or angular ui-router directly interacts with window.location?

我仍然很好奇是什么导致了这种交互,如果角度或角度ui路由器直接与window.location交互?

1 个解决方案

#1


1  

Angular exposes the $location service to interact with the window.location object and I'm pretty sure ui-router uses that and not the window.location object directly. You can decorate the $location service from your config function to intercept all calls to the $location service and provide your own implementation that does not use window.location.

Angular公开$ location服务与window.location对象交互,我很确定ui-router直接使用它而不是window.location对象。您可以从配置函数中修饰$ location服务,以拦截对$ location服务的所有调用,并提供不使用window.location的您自己的实现。

e.g. (highly simplified):

例如(高度简化):

$provide.decorate('$location', function($delegate) {
    var currentUrl = '';
    //we base the proxy on the original
    var locationProxy = Object.create($delegate);
    //and overwrite what we need
    locationProxy.url = function(newUrl) {
        if (newUrl) {
            $rootScope.$broadcast('$locationChangeStart' /* other event args here*/);
            currentUrl = newUrl;
            $rootScope.$broadcast('$locationChangeSuccess' /* other args here */);
        } else {
            return currentUrl;
        }
    };

});

It does require you to implement all functions in a compatible way with the original $location service, so it will probably be quite a bit of work.

它确实要求您以与原始$ location服务兼容的方式实现所有功能,因此它可能会有相当多的工作。

#1


1  

Angular exposes the $location service to interact with the window.location object and I'm pretty sure ui-router uses that and not the window.location object directly. You can decorate the $location service from your config function to intercept all calls to the $location service and provide your own implementation that does not use window.location.

Angular公开$ location服务与window.location对象交互,我很确定ui-router直接使用它而不是window.location对象。您可以从配置函数中修饰$ location服务,以拦截对$ location服务的所有调用,并提供不使用window.location的您自己的实现。

e.g. (highly simplified):

例如(高度简化):

$provide.decorate('$location', function($delegate) {
    var currentUrl = '';
    //we base the proxy on the original
    var locationProxy = Object.create($delegate);
    //and overwrite what we need
    locationProxy.url = function(newUrl) {
        if (newUrl) {
            $rootScope.$broadcast('$locationChangeStart' /* other event args here*/);
            currentUrl = newUrl;
            $rootScope.$broadcast('$locationChangeSuccess' /* other args here */);
        } else {
            return currentUrl;
        }
    };

});

It does require you to implement all functions in a compatible way with the original $location service, so it will probably be quite a bit of work.

它确实要求您以与原始$ location服务兼容的方式实现所有功能,因此它可能会有相当多的工作。