Spec-Zone.ru › Angular.js 1.6

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

Сервис $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

  • $location API

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

Spec-Zone.ru

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