javascript 在没有无限摘要的情况下从 Angular 成功调用 history.pushState()?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22914228/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 00:01:22  来源:igfitidea点击:

Successfully Call history.pushState() from Angular Without Inifinite Digest?

javascripthtmlangularjs

提问by Blaskovicz

Is there a way to call history.pushState()without angular going into an infinite digest loop?

有没有办法在history.pushState()没有角度进入无限摘要循环的情况下进行调用?

I'm trying to migrate my app from backend routing to frontend routing and all the stackoverflow posts/google resources don't seem to have an answer.

我正在尝试将我的应用程序从后端路由迁移到前端路由,并且所有 stackoverflow 帖子/谷歌资源似乎都没有答案。

回答by Torsten Uhlmann

This is what we do in an Angular 1.2.16 app based on this github comment: https://github.com/angular/angular.js/issues/3924#issuecomment-48592773

这是我们在基于此 github 评论的 Angular 1.2.16 应用程序中所做的:https: //github.com/angular/angular.js/issues/3924#issuecomment-48592773

$location.url(myNewUrl);
$location.replace();
$window.history.pushState(null, 'any', $location.absUrl());

This code is part of a controller. I'm using it to add a query param to the url without wanting to reload the page. It works in our case.

此代码是控制器的一部分。我正在使用它向 url 添加查询参数,而不想重新加载页面。它适用于我们的情况。

回答by Daniel Bonnell

I recently encountered a variation of this problem myself and none of the answers here worked for me in isolation. history.pushStatewas defined, but only worked if called from the console. I was able to come up with a solution by consolidating a few of the answers here. Here is the code I used to solve this problem:

我最近自己遇到了这个问题的一个变体,这里没有一个答案单独对我有用。history.pushState已定义,但仅在从控制台调用时才有效。我能够通过在此处合并一些答案来提出解决方案。这是我用来解决这个问题的代码:

// Configure $locationProvider html5Mode
app.config(['$locationProvider', function($locationProvider) {
    $locationProvider.html5Mode({ enabled: true, requireBase: false, rewriteLinks: false });
}]);

// In controller
$window.history.pushState(null, 'Page Title', '/some_new_url');

I'm running Angular 1.5.5.

我正在运行 Angular 1.5.5。

回答by clint

Use the rewriteLinks option on the $locationProvider html5Mode object:

在 $locationProvider html5Mode 对象上使用 rewriteLinks 选项:

    pageModule.config(function($locationProvider) {
        $locationProvider.html5Mode({
            enabled: true,
            requireBase: false,
            rewriteLinks: false
        });
    });

Afterwards, you should be able to use the $location service properly, such as:

之后,您应该可以正常使用 $location 服务,例如:

    this.$location.path("/mynewpath");

回答by Blaskovicz

I was able to come up with a solution that works with angular 1.2.15.

我能够想出一个适用于 angular 1.2.15 的解决方案。

The gist of it is to add a targetattribute to each link and then use the $locationservice to change the location.

它的要点是为target每个链接添加一个属性,然后使用该$location服务更改位置。

Based on the current angular code, anchor tags that have a target attribute are ignored (note that this solution may eventually break).

根据当前的 angular 代码,具有 target 属性的锚标记将被忽略(请注意,此解决方案最终可能会中断)。

To do this, ensure this javascript runs beforeangular:

为此,请确保此 javascriptangular之前运行:

// prevent angular from taking over link clicks until we have frontend routing
$(document.documentElement).on("click","a",function(event) {
  var elem = $(this), target = elem.attr("target");
  if(!target) {
    elem.attr("target","_self");
    setTimeout(function() {
      elem.removeAttr("target");
    });
  }
});

After that, configure your location provider to use html5mode:

之后,将您的位置提供程序配置为使用 html5mode:

  angular.module("App", ["App.controllers"]).config([
    "$locationProvider", function($locationProvider) {
      if (history.pushState) {
        $locationProvider.html5Mode(true);
      }
    }
  ]);

Now, in your controller, inject the location service and use it normally:

现在,在您的控制器中,注入定位服务并正常使用它:

angular.module("App.controllers",[]).controllers("SomeController", ["$scope", "$location", function($scope,$location){
    $scope.updateLocation = function() {
      if (history.pushState) {
        $location.path("/new/path/here");
      }
    };
  }]);