Отключить манипулирование URL в AngularJS

Я пытаюсь написать свое первое веб-приложение с Angular.

В обычном режиме (html5Mode выключен) Angular заставляет хеш-часть адреса выглядеть как «путь» (добавив начальный «/») и кодирует специальные символы — например, он позволяет использовать один «?» и "#" в хеше и заменяет остальные на %3F и %23.

Есть ли способ отключить эту функцию? Я не хочу использовать функции $locationProvider / $routeProvider — я хочу сам проанализировать хэш (в моем случае пользователь введет некоторый «свободный текст», в хеше для поиска внутри моего сайта).

Я читал, что routeProvider нельзя настроить на использование регулярных выражений...

Если htmlMode включен, то хэш-часть адреса не обязательно должна выглядеть как путь (без ведущего "/"), но она по-прежнему кодирует специальные символы.

Я знаю, что некоторые браузеры могут в любом случае кодировать/экранировать специальные символы, но если пользователю удалось ввести некоторые специальные символы в адресную строку, я не хочу его менять.

Спасибо


person Oren    schedule 04.09.2013    source источник


Ответы (5)


Не уверен в побочных эффектах этого, но он выполняет свою работу. Обратите внимание, что это отключит все манипуляции с местоположением из приложения angular, даже если это предполагалось.

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

Вариант ES6:

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

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

Протестировано в Chrome 30, IE9, IE10.
На основе https://stackoverflow.com/a/16678065/369724

person grae.kindel    schedule 07.11.2013
comment
Да, я давно отказался от этой идеи... Просто для протокола: я принимаю ваш ответ, хотя и не проверял его. - person Oren; 07.11.2013
comment
Спасибо. Надеюсь, кто-то из команды angularjs наткнется на это и скажет мне, что есть правильный путь. Это решение потребовало много проб/ошибок и не было найдено, пока я не начал читать исходный код angular. Клиент теперь доволен, и я собираюсь отказаться от фреймворка, как только у меня будет время. Это впечатляющая игрушка, но оказалось, что ее непрактично изучать и расширять. - person grae.kindel; 07.11.2013
comment
Angular пытается манипулировать местоположением, что приводит к бесконечному циклу. - person gronke; 29.12.2013
comment
Этот код не работает, когда вы используете ng-include в любом месте страницы. Он просто перестает работать и выдает множество ошибок. - person kazy; 14.10.2014
comment
Кажется, это хороший обходной путь для angularjs 1.4.3. ng-include тоже работает. - person lestersconyers; 28.09.2015
comment
У меня сработало идеально, когда я использовал angular с PJAX в одном проекте! - person Elya Livshitz; 11.11.2015
comment
Спаситель! Потребовалось много времени, чтобы найти это, но это именно то, что мне было нужно. - person Cerbrus; 03.08.2018

Я использую локальную копию angular.js. Ищи

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

а также

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

закомментируйте соответствующие строки, и angularjs остановит просмотр изменений URL-адреса местоположения.

person Yang Zhang    schedule 12.01.2015
comment
спасибо, было бы так просто сделать это в angularjs - person Elger Mensonides; 13.06.2015

Если я правильно помню, маршрутизация Angular не обязательна, но тогда вы должны позаботиться о перезагрузке контроллеров, представлений и т. д.

person Adam    schedule 07.11.2013
comment
Это не обязательно, но всегда включено. Вы увидите это, если у вас есть страница (foo.html#abc). Если вы перезагрузите его, он станет (foo.html#/abc). Конфликт, который у меня был, был связан с ошибкой API window.history при переходе pushState(...);back();forward(); потому что angular заменял URL-адрес, поэтому история пересылки была потеряна, хотя я вообще не использовал маршрутизацию в угловой части страницы. - person grae.kindel; 07.11.2013
comment
Я бы попробовал кастомную сборку Angular, хотя сам никогда этого не делал :) Дьявол кроется в src/ng/location.js. Ссылка на этот файл должна быть удалена из angularFiles.js, чтобы Grunt не упаковал его. Я полагаю, вам также следует удалить ссылку на $LocationProvider из src/AngularPublic.js, чтобы избежать ошибок. - person Adam; 14.11.2013

Спасибо за ответ @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;
    }]);
}]);

Протестировано в Chrome 69, Firefox 62.

УгловойJS 1.7.4

person Dragon    schedule 16.10.2018
comment
Привет, Дракон. Не могли бы вы настроить этот ответ, чтобы использовать остальные параметры? В противном случае EsLint жалуется на приведенный выше код. - person Naomi; 23.09.2019
comment
@Наоми Готово. (предпочитают остальные параметры) - person Dragon; 24.09.2019

Обходной путь от @greg.kindel (принятое решение) у меня не сработал. Он выдал много ошибок о бесконечном цикле дайджеста. Я использую Angular 1.5.8.

Я смог настроить этот обходной путь следующим образом, чтобы все заработало. Я надеюсь, что это спасет кого-то еще от горя.

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;
    }]);
  }])
person DJ Jain    schedule 29.04.2020