javascript 关闭 AngularJS 中的 URL 操作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18611214/
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-27 12:34:55  来源:igfitidea点击:

Turn off URL manipulation in AngularJS

javascriptangularjsaddress-barlocation-providerroute-provider

提问by Oren

I'm trying to write my first web-app with Angular.

我正在尝试使用 Angular 编写我的第一个网络应用程序。

In the normal mode (html5Mode off), Angular forces the address's hash part to look like a "path" (adding a leading "/"), and encodes special characters - for example, it allows a single "?" and "#" in the hash and replaces the others with %3F and %23.

在正常模式下(html5Mode 关闭),Angular 强制地址的哈希部分看起来像“路径”(添加前导“/”),并编码特殊字符 - 例如,它允许单个“?” 和散列中的“#”,并用 %3F 和 %23 替换其他的。

Is there a way to turn this feature off? I don't want to use the $locationProvider/ $routeProviderfeatures - I want to parse the hash myself (In my case, the user's will enter some "free text" in the hash to search inside my website).

有没有办法关闭这个功能?我不想使用$locationProvider/ $routeProvider功能 - 我想自己解析散列(在我的情况下,用户将在散列中输入一些“自由文本”以在我的网站内搜索)。

I read that the routeProvider cannot be configured to use regular expressions...

我读到无法将 routeProvider 配置为使用正则表达式...

If htmlMode is turned on, then the address's hash part is not forced to look like a path (no leading "/"), but it still encodes special characters.

如果 htmlMode 被打开,那么地址的哈希部分不会被强制看起来像一个路径(没有前导“/”),但它仍然编码特殊字符。

I'm aware that some browsers might encode/escape the special characters anyway, but if the user managed to enter some special characters in its address bar then I don't want to change it.

我知道有些浏览器无论如何可能会对特殊字符进行编码/转义,但是如果用户设法在其地址栏中输入了一些特殊字符,那么我不想更改它。

Thanks

谢谢

回答by greg.kindel

Not sure of the side effects of this, but it gets the job done. Note that it will disable all location manipulation from the angular app, even if intended.

不确定这样做的副作用,但它可以完成工作。请注意,即使有意,它也会禁用 angular 应用程序的所有位置操作。

angular.module('sample', [])
    .config( ['$provide', function ($provide){
        $provide.decorator('$browser', ['$delegate', function ($delegate) {
            $delegate.onUrlChange = function () {};
            $delegate.url = function () { return ""};
            return $delegate;
        }]);
    }]);

ES6 variant:

ES6 变体:

angular.module('sample', [])
    .config(["$provide", $provide => {
        $provide.decorator("$browser", ["$delegate", $delegate => {
            $delegate.onUrlChange = () => { };
            $delegate.url = () => "";

            return $delegate;
        }]);
    }]);

Tested in Chrome 30, IE9, IE10.
Inspired by https://stackoverflow.com/a/16678065/369724

在 Chrome 30、IE9、IE10 中测试。
灵感来自https://stackoverflow.com/a/16678065/369724

回答by Yang Zhang

I use a local copy of angular.js. Search for

我使用 angular.js 的本地副本。搜索

$browser.onUrlChange(function(newUrl, newState) {

and

$rootScope.$watch(function $locationWatch() {

comment out the corresponding lines and angularjs will stop watch for location url changes.

注释掉相应的行,angularjs 将停止监视位置 url 的变化。

回答by Dragon

Thank @greg.kindel 's answer, you help me find a solution to solve anchor problem. This code let AngularJS app IGNORE some hash pattern, keep it working like browser default. I don't need enable html5Mode, and ngRoute still working. :)

感谢@greg.kindel 的回答,你帮我找到了解决锚点问题的方法。这段代码让 AngularJS 应用忽略了一些哈希模式,让它像浏览器默认一样工作。我不需要启用 html5Mode,并且 ngRoute 仍在工作。:)

app.config(['$provide', function ($provide) {
    $provide.decorator('$browser', ['$delegate', '$window', function ($delegate, $window) {
        // normal anchors
        let ignoredPattern = /^#[a-zA-Z0-9].*/;
        let originalOnUrlChange = $delegate.onUrlChange;
        $delegate.onUrlChange = function (...args) {
            if (ignoredPattern.test($window.location.hash)) return;
            originalOnUrlChange.apply($delegate, args);
        };
        let originalUrl = $delegate.url;
        $delegate.url = function (...args) {
            if (ignoredPattern.test($window.location.hash)) return $window.location.href;
            return originalUrl.apply($delegate, args);
        };
        return $delegate;
    }]);
}]);

Tested in Chrome 69, Firefox 62

在 Chrome 69、Firefox 62 中测试

AngularJS 1.7.4

AngularJS 1.7.4

回答by DJ Jain

The workaround from @greg.kindel (the accepted solution) didn't work for me. It threw lots of errors about an infinite digest loop. I'm using Angular 1.5.8.

@greg.kindel(已接受的解决方案)的解决方法对我不起作用。它抛出了很多关于无限摘要循环的错误。我正在使用 Angular 1.5.8。

I was able to adjust that workaround to the following to get things working. I hope it saves someone else grief.

我能够将该解决方法调整为以下内容以使事情正常进行。我希望它可以避免其他人的悲伤。

angular.module('sample', [])
  .config(['$provide', function ($provide) {
    $provide.decorator('$browser', ['$delegate', '$window', function ($delegate, $window) {
      $delegate.onUrlChange = function () {};
      //
      // HACK to stop Angular routing from manipulating the URL
      //
      // The url() function seems to get used in two different modes.
      //
      // Mode 1 - Zero arguments
      // There are no arguments given, in which case it appears that the caller is expected the
      // browser's current URL (a string response).
      //
      // Mode 2 - Three arguments
      // It receives three arguments (url, some_boolean, null).  It seems the caller is expecting
      // the browser's URL to be updated to the given value.  The result of this function call is
      // expected to be the $delegate itself, which will subsequently get called with no arguments
      // to check the browser's URL.
      //
      // The Hack:
      // We save the URL so that we can lie to the caller that the URL has been updated to what was
      // requested, but in reality, we'll do nothing to alter the URL.
      //
      var savedUrl = null
      $delegate.url = function (url, ...args) {
        if (!!url) {
          savedUrl = url;
          return $delegate;
        } else {
          return !!savedUrl ? savedUrl : $window.location.href;
        }
      };
      return $delegate;
    }]);
  }])

回答by Adam

If I recall correctly, Angular's routing is not obligatory, but then you must take care of reloading controllers, views, etc.

如果我没记错的话,Angular 的路由不是强制性的,但是您必须注意重新加载控制器、视图等。