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.

Я знаю, что это взлом, но это решило проблему для меня.

Другие вопросы по тегам