Spec-Zone.ru › Angular.js 1.8

Улучшить эту статьюИспользование сервиса $location

Сервис $location анализирует URL в адресной строке браузера (на основе window.location) и делает URL доступным для вашего приложения. Изменения в URL адресной строки отображаются в сервисе $location, а изменения в $location отражаются в адресной строке браузера.

Сервис $location:

  • Предоставляет доступ к текущему URL в адресной строке браузера, так что вы можете:
    • Отслеживать и наблюдать за URL.
    • Изменять URL.
  • Обеспечивает синхронизацию между собой и URL браузера, когда пользователь:
    • Изменяет адрес в адресной строке браузера.
    • Нажимает кнопки «Назад» или «Вперед» в браузере (или кликает на ссылку в истории).
    • Нажимает на ссылку на странице.
  • Представляет объект URL в виде набора методов (протокол, хост, порт, путь, поиск, хэш).

Сравнение $location и window.location

window.location Сервис $location
назначение предоставляет чтение/запись текущего местоположения браузера то же
API предоставляет «сырой» объект со свойствами, которые можно напрямую изменять предоставляет методы в стиле jQuery для получения и установки значений
интеграция с жизненным циклом приложения AngularJS нет знает обо всех внутренних фазах жизненного цикла, интегрируется с $watch, ...
бесшовная интеграция с HTML5 API нет да (с резервным вариантом для устаревших браузеров)
осознает корневой каталог/контекст, из которого загружено приложение нет — window.location.pathname возвращает "/docroot/actual/path" да — $location.path() возвращает "/actual/path"

Когда следует использовать $location?

Всякий раз, когда ваше приложение должно реагировать на изменения текущего URL или если вы хотите изменить текущий URL в браузере.

Что он не делает?

Он не вызывает полной перезагрузки страницы при изменении URL браузера. Чтобы перезагрузить страницу после изменения URL, используйте более низкоуровневый API, $window.location.href.

Обзор API

Сервис $location может вести себя по-разному в зависимости от конфигурации, заданной при его инициализации. По умолчанию подходит для многих приложений, но для других конфигурирование позволит использовать новые возможности.

После инициализации сервиса $location, можно взаимодействовать с ним с помощью методов получения и установки значений в стиле jQuery, которые позволяют получать или изменять текущий URL в браузере.

Конфигурация сервиса $location

Чтобы настроить сервис $location, получите $locationProvider и задайте параметры следующим образом:

  • html5Mode(mode): {boolean|Object}
    false или {enabled: false} (по умолчанию) — см. Режим Hashbang
    true или {enabled: true} — см. Режим HTML5
    {..., requireBase: true/false} (только для режима HTML5) — см. Относительные ссылки
    {..., rewriteLinks: true/false/'string'} (только для режима HTML5) — см. Переписывание ссылок HTML
    По умолчанию:

    {
      enabled: false,
      requireBase: true,
      rewriteLinks: true
    }
    
  • hashPrefix(prefix): {string}
    Префикс, используемый для Hashbang URL (используется в режиме Hashbang или в устаревших браузерах в режиме HTML5).
    По умолчанию: '!'

Пример конфигурации

$locationProvider.html5Mode(true).hashPrefix('*');

Методы получения и установки

Сервис $location предоставляет методы получения только для чтения для частей URL (absUrl, protocol, host, port) и методы получения/установки для url, path, search, hash:

// get the current path
$location.path();

// change the path
$location.path('/newValue')

Все методы установки возвращают тот же объект $location для цепочки вызовов. Например, чтобы изменить несколько сегментов сразу, можно использовать цепочку установок:

$location.path('/newValue').search({key: value});

Метод replace

Существует специальный метод replace, который можно использовать для того, чтобы сообщить сервису $location, что при следующей синхронизации сервиса $location с браузером последняя запись истории должна быть заменена, а не создана новая. Это полезно при реализации перенаправлений, которые в противном случае нарушат работу кнопки «Назад» (возврат приведет к повторному вызову перенаправления). Чтобы изменить текущий URL без создания новой записи в истории браузера, можно вызвать:

$location.path('/someNewPath');
$location.replace();
// or you can chain these as: $location.path('/someNewPath').replace();

Обратите внимание, что установщики не обновляют window.location немедленно. Вместо этого, сервис $location осознает жизненный цикл scope и объединяет несколько мутаций $location в одно «сохранение» в объект window.location во время фазы жизненного цикла scope $digest. Поскольку несколько изменений состояния $location будут переданы браузеру как одно изменение, достаточно вызвать метод replace() один раз, чтобы сделать все «сохранение» операцией замены, а не добавлением в историю браузера. После обновления браузера сервис $location сбрасывает флаг, установленный методом replace(), и будущие мутации будут создавать новые записи истории, если метод replace() не будет вызван снова.

Методы установки и кодировка символов

Вы можете передавать специальные символы в сервис $location , и он будет кодировать их в соответствии с правилами, указанными в RFC 3986. При обращении к методам:

  • Все значения, передаваемые методам установки $location, path(), search(), hash(), кодируются.
  • Методы получения (вызовы методов без параметров) возвращают декодированные значения для следующих методов path(), search(), hash().
  • При вызове метода absUrl(), возвращаемое значение — полный URL с закодированными сегментами.
  • При вызове метода url(), возвращаемое значение — путь, поиск и хэш в формате /path?search=a&b=c#hash. Сегменты также закодированы.

Режимы Hashbang и HTML5

Сервис $location имеет два режима конфигурации, которые контролируют формат URL в адресной строке браузера: режим Hashbang (по умолчанию) и режим HTML5, основанный на использовании API истории HTML5. Приложения используют одинаковый API в обоих режимах, и сервис $location будет работать с соответствующими сегментами URL и API браузера для облегчения изменения URL браузера и управления историей.

Режим Hashbang Режим HTML5
конфигурация по умолчанию { html5Mode: true }
формат URL Hashbang URL во всех браузерах обычные URL в современных браузерах, Hashbang URL в старых браузерах
переписывание ссылок <a href=""> нет да
требует конфигурации на стороне сервера нет да

Режим Hashbang (режим по умолчанию)

В этом режиме $location использует Hashbang URL во всех браузерах. AngularJS также не перехватывает и не переписывает ссылки в этом режиме. То есть ссылки работают как ожидается, а также выполняют полную перезагрузку страницы, когда были изменены части URL, кроме фрагмента хэша.

it('should show example', function() {
  module(function($locationProvider) {
    $locationProvider.html5Mode(false);
    $locationProvider.hashPrefix('!');
  });
  inject(function($location) {
    // open http://example.com/base/index.html#!/a
    expect($location.absUrl()).toBe('http://example.com/base/index.html#!/a');
    expect($location.path()).toBe('/a');

    $location.path('/foo');
    expect($location.absUrl()).toBe('http://example.com/base/index.html#!/foo');

    expect($location.search()).toEqual({});
    $location.search({a: 'b', c: true});
    expect($location.absUrl()).toBe('http://example.com/base/index.html#!/foo?a=b&c');

    $location.path('/new').search('x=y');
    expect($location.absUrl()).toBe('http://example.com/base/index.html#!/new?x=y');
  });
});

Режим HTML5

В режиме HTML5 сервис $location взаимодействует с URL браузера через API истории HTML5 для получения и установки значений пути и поиска. Это позволяет использовать обычные сегменты пути и поиска URL вместо их эквивалентов с Hashbang. Если API истории HTML5 не поддерживается браузером, сервис $location автоматически переходит к Hashbang URL. Это избавляет вас от необходимости беспокоиться о том, поддерживает ли браузер, отображающий ваше приложение, API истории; сервис $location прозрачно использует лучший доступный вариант.

  • Открытие обычного URL в устаревшем браузере —> перенаправляет на Hashbang URL
  • Открытие Hashbang URL в современном браузере —> переписывает на обычный URL

Обратите внимание, что в этом режиме AngularJS перехватывает все ссылки (подлежащие правилам «Переписывание ссылок HTML» ниже) и обновляет URL таким образом, чтобы никогда не происходила полная перезагрузка страницы.

it('should show example', function() {
  module(function($locationProvider) {
    $locationProvider.html5Mode(true);
    $locationProvider.hashPrefix('!');
  });
  inject(function($location) {
    // in browser with HTML5 history support:
    // open http://example.com/#!/a -> rewrite to http://example.com/a
    // (replacing the http://example.com/#!/a history record)
    expect($location.path()).toBe('/a');

    $location.path('/foo');
    expect($location.absUrl()).toBe('http://example.com/foo');

    expect($location.search()).toEqual({});
    $location.search({a: 'b', c: true});
    expect($location.absUrl()).toBe('http://example.com/foo?a=b&c');

    $location.path('/new').search('x=y');
    expect($location.url()).toBe('/new?x=y');
    expect($location.absUrl()).toBe('http://example.com/new?x=y');
  });
});

it('should show example (when browser doesn\'t support HTML5 mode', function() {
  module(function($provide, $locationProvider) {
    $locationProvider.html5Mode(true);
    $locationProvider.hashPrefix('!');
    $provide.value('$sniffer', {history: false});
  });
  inject(initBrowser({ url: 'http://example.com/new?x=y', basePath: '/' }),
    function($location) {
    // in browser without html5 history support:
    // open http://example.com/new?x=y -> redirect to http://example.com/#!/new?x=y
    // (again replacing the http://example.com/new?x=y history item)
    expect($location.path()).toBe('/new');
    expect($location.search()).toEqual({x: 'y'});

    $location.path('/foo/bar');
    expect($location.path()).toBe('/foo/bar');
    expect($location.url()).toBe('/foo/bar?x=y');
    expect($location.absUrl()).toBe('http://example.com/#!/foo/bar?x=y');
  });
});

Резервный вариант для устаревших браузеров

Для браузеров, поддерживающих API истории HTML5, $location использует API истории HTML5 для записи пути и поиска. Если API истории не поддерживается браузером, $location предоставляет Hashbang URL. Это избавляет вас от необходимости беспокоиться о том, поддерживает ли браузер, отображающий ваше приложение, API истории; сервис $location делает это прозрачным для вас.

Переписывание ссылок HTML

При использовании режима API истории HTML5 вам не понадобятся специальные ссылки Hashbang. Вам нужно лишь указать обычные ссылки URL, такие как: <a href="/some?foo=bar">link</a>

Когда пользователь нажимает на эту ссылку:

  • В устаревшем браузере URL меняется на /index.html#!/some?foo=bar
  • В современном браузере URL меняется на /some?foo=bar

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

  • Ссылки, содержащие элемент target,
    Пример: <a href="/ext/link?a=b" target="_self">link</a>
  • Абсолютные ссылки, ведущие на другой домен,
    Пример: <a href="http://angularjs.org/">link</a>
  • Ссылки, начинающиеся с '/', ведущие к другому базовому пути,
    Пример: <a href="/not-my-base/link">link</a>

Если mode.rewriteLinks установлено в false в объекте конфигурации mode , переданном в $locationProvider.html5Mode(), браузер выполнит полную перезагрузку страницы для каждой ссылки. mode.rewriteLinks также может быть установлено в строку, что позволит переписывать ссылки только для элементов anchor, которые имеют данный атрибут.

Например, если mode.rewriteLinks установлено в 'internal-link':

  • <a href="/some/path" internal-link>link</a> будет переписан
  • <a href="/some/path">link</a> выполнит полную перезагрузку страницы

Обратите внимание, что нормализация имен атрибутов здесь не применяется, поэтому 'internalLink' не будет соответствовать 'internal-link'.

Относительные ссылки

Убедитесь, что все относительные ссылки, изображения, скрипты и т. д. прописаны правильно. AngularJS требует указания базового URL в заголовке вашего основного HTML-файла (<base href="/my-base/index.html">) , если html5Mode.requireBase не установлено в false в объекте определения html5Mode, переданном в $locationProvider.html5Mode(). В этом случае относительные URL всегда будут разрешаться к этому базовому URL, даже если начальный URL документа был другим.

Существует одно исключение: ссылки, содержащие только фрагмент хеша (например, <a href="#target">), изменят только $location.hash() и не изменят URL иначе. Это полезно для прокрутки до якорей на одной странице без необходимости знать, на какой странице пользователь находится в данный момент.

Серверная сторона

Использование этого режима требует переписывания URL на серверной стороне, в основном необходимо переписать все ссылки на точку входа в ваше приложение (например, index.html). Необходимо также использовать тег <base>, так как он позволяет AngularJS различать часть URL, являющуюся базовой частью приложения, и путь, который должен обрабатываться приложением.

Ограничения base href

Сервис $location не может работать должным образом, если текущий URL находится за пределами URL, указанного как base href. Это может иметь неожиданные и запутанные последствия...

Рассмотрим базовый href, заданный следующим образом: <base href="/base/"> (т. е. приложение находится в папке под названием /base). URL /base фактически находится за пределами приложения (он относится к файлу base в корневой папке /).

Если вы хотите иметь возможность переходить к приложению по URL, такому как /base, то вы должны убедиться, что ваш сервер настроен на перенаправление таких запросов на /base/.

Дополнительную информацию см. в https://github.com/angular/angular.js/issues/14018.

Передача ссылок между разными браузерами

Благодаря возможности переписывания в режиме HTML5, ваши пользователи смогут открывать обычные URL-ссылки в старых браузерах и ссылки с hashbang в современных браузерах:

  • Современные браузеры будут переписывать URL с hashbang на обычные URL.
  • Старые браузеры будут перенаправлять обычные URL на URL с hashbang.

Здесь вы можете увидеть два $location экземпляра, которые показывают разницу между режимом Html5 и режимом Html5 Fallback. Обратите внимание, что для имитации различных уровней поддержки браузеров экземпляры $location подключены к сервису fakeBrowser, который вам не нужно настраивать в реальных проектах.

Обратите внимание, что при вводе URL с hashbang в первый браузер (или наоборот) он не переписывает/перенаправляет на обычный/hashbang URL, так как это преобразование происходит только при парсинге начального URL = при перезагрузке страницы.

В этих примерах мы используем <base href="/base/index.html" />. Входные данные представляют собой адресную строку браузера.

Браузер в режиме HTML5
Браузер в режиме HTML5 Fallback (режим Hashbang)

Ограничения

Переход при перезагрузке страницы

Сервис $location позволяет изменить только URL; он не позволяет перезагрузить страницу. Если вам нужно изменить URL и перезагрузить страницу или перейти на другую страницу, используйте более низкоуровневый API, $window.location.href.

Использование $location вне жизненного цикла области видимости

$location знает о жизненном цикле области видимости AngularJS scope. Когда URL изменяется в браузере, он обновляет $location и вызывает $apply, чтобы все $наблюдатели / $наблюдатели получили уведомление. Когда вы изменяете $location внутри стадии $digest, все в порядке; $location распространит это изменение в браузер и уведомит всех $наблюдателей / $наблюдателей. Если вы хотите изменить $location извне AngularJS (например, через событие DOM или во время тестирования), вы должны вызвать $apply, чтобы распространить изменения.

$location.path() и префиксы ! или /

Путь всегда должен начинаться с косой черты (/); установщик $location.path() добавит косую черту, если она отсутствует.

Обратите внимание, что префикс ! в режиме hashbang не является частью $location.path(); на самом деле это hashPrefix.

Обход вашего приложения

Большинство современных поисковых систем способны обходить приложения AJAX с динамическим содержимым, при условии, что все включенные ресурсы доступны ботам-роботам-поисковикам.

Также существует специальная схема обхода AJAX, разработанная Google, которая позволяет ботам обходить статический эквивалент динамически сгенерированной страницы, но эта схема устарела, и поддержка её может различаться в зависимости от поисковой системы.

Тестирование с помощью сервиса $location

При использовании сервиса $location во время тестирования вы находитесь вне жизненного цикла области видимости Angular. Это означает, что вы несете ответственность за вызов scope.$apply().

describe('serviceUnderTest', function() {
  beforeEach(module(function($provide) {
    $provide.factory('serviceUnderTest', function($location) {
      // whatever it does...
    });
  });

  it('should...', inject(function($location, $rootScope, serviceUnderTest) {
    $location.path('/new/path');
    $rootScope.$apply();

    // test whatever the service should do...

  }));
});

Двунаправленная привязка к $location

Так как $location использует геттеры/сеттеры, вы можете использовать ng-model-options="{ getterSetter: true }" для привязки его к ngModel:

Связанный API

  • $location API

© 2010–2020 Google, Inc.
Licensed under the Creative Commons Attribution License 3.0.
https://code.angularjs.org/1.8.2/docs/guide/$location

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API