Улучшить эту документациюЧто это делает?
Сервис $location анализирует URL в адресной строке браузера (на основе window.location) и делает URL доступным для вашего приложения. Изменения в URL адресной строки отражаются в сервисе $location , а изменения в $location отражаются в адресной строке браузера.
Сервис $location:
- Предоставляет текущий URL в адресной строке браузера, поэтому вы можете:
- Отслеживать и наблюдать за URL.
- Изменять URL.
- Поддерживает синхронизацию между собой и URL браузера, когда пользователь:
- Изменяет адрес в адресной строке браузера.
- Нажимает кнопку «Назад» или «Вперед» в браузере (или кликает по ссылке в истории).
- Нажимает на ссылку на странице.
- Представляет объект URL в виде набора методов (протокол, хост, порт, путь, поиск, хэш).
Сравнение $location и window.location
| window.location | Сервис $location | |
|---|---|---|
| назначение | предоставляет чтение/запись текущего расположения браузера | то же самое |
| API | экспонирует «сырой» объект с свойствами, которые можно напрямую изменять | экспонирует методы в стиле jQuery для получения и установки значений |
| интеграция с жизненным циклом приложения AngularJS | нет | знает о всех внутренних фазах жизненного цикла, интегрируется с $watch и т.д. |
| бесшовная интеграция с API HTML5 | нет | да (с резервным вариантом для старых браузеров) |
| осознаёт docroot/контекст загрузки приложения | нет - 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}(по умолчанию) - см. Режим с хеш-символом
trueили{enabled: true}- см. Режим HTML5
{..., requireBase: true/false}(только для режима HTML5) - см. Относительные ссылки
{..., rewriteLinks: true/false/'string'}(только для режима HTML5) - см. Переписывание ссылок HTML
По умолчанию:{ enabled: false, requireBase: true, rewriteLinks: true } -
hashPrefix(prefix):
{string}
Префикс, используемый для URL с хеш-символом (используется в режиме с хеш-символом или в старых браузерах в режиме 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. Сегменты также кодируются.
Режимы с хеш-символом и HTML5
Сервис $location имеет два режима конфигурации, которые управляют форматом URL в адресной строке браузера: режим с хеш-символом (по умолчанию) и режим HTML5, основанный на использовании API истории HTML5. Приложения используют один и тот же API в обоих режимах, и сервис $location будет работать с соответствующими сегментами URL и API браузера для облегчения изменения URL браузера и управления историей.
| Режим с хеш-символом | Режим HTML5 | |
|---|---|---|
| конфигурация | по умолчанию | { html5Mode: true } |
| формат URL | URL с хеш-символом во всех браузерах | обычные URL в современных браузерах, URL с хеш-символом в старых браузерах |
| переписывание ссылок <a href=""> | нет | да |
| требует конфигурации сервера | нет | да |
Режим с хеш-символом (режим по умолчанию)
В этом режиме $location использует 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 вместо их эквивалентов с хеш-символом. Если API истории HTML5 не поддерживается браузером, сервис $location автоматически переходит к использованию URL с хеш-символом. Это освобождает вас от необходимости беспокоиться о том, поддерживает ли браузер, отображающий ваше приложение, API истории или нет; сервис $location прозрачно использует лучший доступный вариант.
- Открытие обычного URL в старом браузере —> перенаправление на URL с хеш-символом
- Открытие 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 предоставляет URL с хеш-символом. Это освобождает вас от необходимости беспокоиться о том, поддерживает ли браузер, отображающий ваше приложение, API истории или нет; сервис $location делает это прозрачным для вас.
Переписывание ссылок HTML
При использовании режима API истории HTML5 вам не нужны специальные ссылки с хеш-символом. Всё, что вам нужно, это указать обычные ссылки 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 также может быть установлено в строку, которая включит переписывание ссылок только для элементов якоря, имеющих указанный атрибут.
Например, если 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-ссылки в устаревших браузерах и ссылки с хеш-символом в современных браузерах:
- Современные браузеры будут переписывать URL с хеш-символом на обычные URL.
- Старые браузеры будут перенаправлять обычные URL на URL с хеш-символом.
Здесь вы можете увидеть два $location экземпляра, демонстрирующие разницу между режимом Html5 и Html5 Fallback mode. Обратите внимание, что для имитации различного уровня поддержки браузеров, $location экземпляры подключены к сервису fakeBrowser, который вам не нужно настраивать в реальных проектах.
Обратите внимание, что когда вы вводите URL с хеш-символом в первый браузер (или наоборот), он не переписывает/перенаправляет на обычный/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, чтобы все $watchers / $observers были уведомлены. При изменении $location внутри фазы $digest все в порядке; $location распространит это изменение в браузер и уведомит все $watchers / $observers. Если вы хотите изменить $location извне AngularJS (например, через событие DOM или во время тестирования) — вы должны вызвать $apply для распространения изменений.
$location.path() и ! или / префиксы
Путь всегда должен начинаться с косой черты (/); установщик $location.path() добавит косую черту, если она отсутствует.
Обратите внимание, что префикс ! в режиме hashbang не является частью $location.path(); он фактически hashPrefix.
Обход вашего приложения
Для индексации вашего AJAX-приложения вам необходимо добавить специальный тег meta в раздел head вашего документа:
<meta name="fragment" content="!" />
Это заставит бота-паука запросить ссылки с параметром _escaped_fragment_, чтобы ваш сервер смог распознать паука и предоставить моментальные снимки HTML. Более подробную информацию об этом методе см. в статье Making AJAX Applications Crawlable.
Тестирование с сервисом $location
При использовании сервиса $location во время тестирования, вы находитесь вне жизненного цикла области видимости Angular scope. Это означает, что вы несете ответственность за вызов 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
В более ранних версиях AngularJS, $location использовал hashPath или hashSearch для обработки методов path и search. В этой версии сервис $location обрабатывает методы path и search, а затем использует полученную информацию для составления URL с хеш-символом (таких как http://server.com/#!/path?search=a), при необходимости.
Изменения в вашем коде
| Навигация внутри приложения | Изменить на |
|---|---|
| $location.href = value $location.hash = value $location.update(value) $location.updateHash(value) | $location.path(path).search(search) |
| $location.hashPath = path | $location.path(path) |
| $location.hashSearch = search | $location.search(search) |
| Навигация вне приложения | Использовать API нижнего уровня |
| $location.href = value $location.update(value) | $window.location.href = value |
| $location[protocol | host | port | path | search] | $window.location[protocol | host | port | path | search] |
| Чтение доступа | Изменить на |
| $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
© 2010–2018 Google, Inc.
Licensed under the Creative Commons Attribution License 4.0.
https://code.angularjs.org/1.6.9/docs/guide/$location