Spec-Zone.ru › Angular.js 1.5

Улучшить эту документациюЧто это делает?

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

Сервис $location:

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

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

window.location Сервис $location
назначение предоставляет чтение/запись текущего расположения браузера то же
API выводит "сырой" объект со свойствами, которые можно напрямую изменять выводит методы в стиле jQuery для получения и установки значений
интеграция с жизненным циклом приложения Angular нет знает о всех внутренних фазах жизненного цикла, интегрируется с $watch, ...
бесшовное интегрирование с API HTML5 нет да (с резервным вариантом для устаревших браузеров)
осознает корневой каталог/контекст, из которого загружено приложение нет — 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}
    Префикс, используемый для URL с Hashbang (используется в режиме 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, что при следующей синхронизации с браузером последняя запись в истории должна быть заменена, а не создана новая. Это полезно при реализации перенаправления, которое в противном случае нарушит работу кнопки "Назад" (переход назад повторно запустит перенаправление). Чтобы изменить текущий URL без создания новой записи в истории браузера, вы можете вызвать:

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

Обратите внимание, что установщики не обновляют window.location немедленно. Вместо этого, сервис $location понимает жизненный цикл scope и объединяет несколько мутаций $location в одну "транзакцию" для объекта window.location во время фазы $digest scope. Поскольку несколько изменений состояния $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 URL с Hashbang во всех браузерах обычные URL в современных браузерах, URL с Hashbang в старых браузерах
перезапись ссылок <a href=""> нет да
требует настройки на стороне сервера нет да

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

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

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

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

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

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

Режим HTML5

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

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

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

it('should show example', inject(
  function($locationProvider) {
    $locationProvider.html5Mode(true);
    $locationProvider.hashPrefix('!');
  },
  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)
    $location.path() === '/a'

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

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

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

    // 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)
    $location.path() === '/new'
    $location.search() === {x: 'y'}

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

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

Для браузеров, которые поддерживают API истории HTML5, $location использует API истории HTML5 для записи пути и поиска. Если API истории не поддерживается браузером, $location предоставляет URL с Hashbang. Это избавляет вас от необходимости беспокоиться о том, поддерживает ли браузер, отображающий ваше приложение, 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'.

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

Убедитесь, что все относительные ссылки, изображения, скрипты и т.д. указаны корректно. Angular требует указать базовый 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>, так как это позволяет Angular различать часть URL, являющуюся базовым адресом приложения, и путь, который должен обрабатываться приложением.

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

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

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

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

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

Отправка ссылок между различными браузерами

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

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

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

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

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

Браузер в режиме HTML5

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

Ограничения

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

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

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

$location знает о жизненном цикле области видимости Angular. При изменении URL в браузере, он обновляет $location и вызывает $apply, чтобы все $watchers / $observers были уведомлены. При изменении $location внутри фазы $digest всё в порядке; $location распространит это изменение в браузере и уведомит все $watchers / $observers. Если вы хотите изменить $location извне Angular (например, через событие DOM или во время тестирования) - вы должны вызвать $apply, чтобы распространить изменения.

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

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

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

Индексация вашего приложения

Для индексирования вашего AJAX-приложения необходимо добавить специальный тег meta в секцию head вашего документа:

<meta name="fragment" content="!" />

Это заставит робота-индексатор запросить ссылки с параметром _escaped_fragment_, чтобы ваш сервер мог распознать робота-индексатор и предоставить снимок HTML. Для получения дополнительной информации об этой технике см. Индексирование AJAX-приложений.

Тестирование с помощью сервиса $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...

  }));
});

Миграция из более ранних версий AngularJS

В более ранних версиях Angular, $location использовал hashPath или hashSearch для обработки методов path и search. В этой версии, сервис $location обрабатывает методы path и search, а затем использует полученную информацию для составления URL с хеш-фрагментом (например, http://server.com/#!/path?search=a), если это необходимо.

Изменения в вашем коде

Навигация внутри приложения Изменить на
$location.href = значение
$location.hash = значение
$location.update(значение)
$location.updateHash(значение)
$location.path(путь).search(поиск)
$location.hashPath = путь $location.path(путь)
$location.hashSearch = поиск $location.search(поиск)
Навигация вне приложения Использовать API низкого уровня
$location.href = значение
$location.update(значение)
$window.location.href = значение
$location[протокол | хост | порт | путь | поиск] $window.location[протокол | хост | порт | путь | поиск]
Чтение Изменить на
$location.hashPath $location.path()
$location.hashSearch $location.search()
$location.href
$location.protocol
$location.host
$location.port
$location.hash
$location.absUrl()
$location.protocol()
$location.host()
$location.port()
$location.path() + $location.search()
$location.path
$location.search
$window.location.path
$window.location.search

Двухсторонняя привязка к $location

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

Связанный API

  • $location API

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

Spec-Zone.ru

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