angular $location, события $route жизненного цикла запускаются дважды, когда браузер кодирует URL
Используя угловой 1.2.10
ОБНОВЛЕНО: проблема также возникает в последних версиях (1.2.21) и бета-версиях (1.3.0-бета.17)
Я предоставил упрощенный пример, который демонстрирует проблему, с которой я сталкиваюсь ниже
По сути, поведение, которое я наблюдаю и пытаюсь предотвратить, заключается в том, что когда мое приложение загружает маршрут, URL-адрес которого автоматически кодируется браузером (например, потому что в значениях параметров есть пробелы или +), я вижу события жизненного цикла сервиса location и $ route запускаются дважды. Используя приведенный ниже пример, самый простой способ воспроизвести это поведение - загрузить приложение и добавить следующие параметры:
?message=test val
?message=test+val
Если вы посмотрите на вывод консоли, то увидите, что в первом примере дважды запускаются обработчики $ locationChangeStart и $ locationChangeSuccess. Основываясь на документации, я считаю, что angular следит за адресной строкой на предмет изменений, и я предполагаю, что она запускает эти события для не кодированного URL, а затем снова после его кодирования.
Есть ли способ предотвратить это?
ПРИМЕЧАНИЕ. Я также заметил, что, несмотря на то, что "+" является допустимой заменой пробела в значении параметра, результирующее значение сохраняет "+"; то есть? message = test + val будет отображаться как 'test + val', а не 'test val'. На эту проблему уже есть билет.
ОБНОВЛЕНИЕ: я открыл этот билет с угловой командой.
<!DOCTYPE html>
<html id="ng-app" data-ng-app="test">
<head>
<script src="angular.js"></script>
<script src="angular-route.js"></script>
<script>
'use strict';
angular.module('test', ['ngRoute'])
.config(function($routeProvider) {
$routeProvider.when('/',
{
template: '{{data.params}}',
controller:'TestCtrl',
resolve:{params: function($route) {return $route.current.params;}}
})
})
.run(function($rootScope) {
$rootScope.$on('$locationChangeStart',function(event, next, current){
console.log(event.name,'current=' + current,'next=' + next);
});
$rootScope.$on('$locationChangeSuccess',function(event, next, current){
console.log(event.name,'current=' + current,'next=' + next,'\n');
});
})
.controller('TestCtrl',function($scope,params){
console.log('Inside TestCtrl');
$scope.data={params:params};});
</script>
</head>
<body>
<div ng-view></div>
</body>
</html>
1 ответ
У меня была такая же проблема. В моем случае это было при попытке обработать историю, и по какой-то причине второй жизненный цикл очищал мои идентификаторы фрагментов, поэтому частичное обновление страницы не работало.
Единственный способ, которым я мог обойти это, - это посмотреть на $location.search(), чтобы увидеть, было ли это допустимое изменение, и вызвать event.preventDefault() в обработчике $locationChangeStart, если это не так. Это предотвращает продолжение работы с обработчиком $ locationChangeSuccess. В вашем случае, вы могли бы проверить location.url(), чтобы увидеть, был ли URL еще закодирован? Если нет, просто завершите цикл и дождитесь запуска закодированного URL.
Я знаю, что это взлом, но это решило проблему для меня.