AngularJS Пейджинг с $location.path, но без перезагрузки ngView

Мое одностраничное приложение загружает домашнюю страницу, и я хочу показать ряд идей. Каждая из идей отображается в анимированном флеш-контейнере с анимацией, отображаемой для переключения между идеями.

Идеи загружаются с использованием $ http:

$scope.flash = new FlashInterface scope:$scope,location:$location

$http.get("/competition.json")
  .success (data) ->
    $scope.flash._init data

Однако, чтобы воспользоваться навигацией по истории и UX, я хочу обновить адресную строку, чтобы отображать правильный URL для каждой идеи, используя $location:

$location.path "/i/#{idea.code}"
$scope.$apply()

Я называю $apply здесь, потому что это событие происходит из контекста AngularJS, т.е. Flash. Я хотел бы, чтобы текущий контроллер / представление оставалось, а представление не перезагружалось. Это очень плохо, потому что перезагрузка представления приводит к выбрасыванию всего флэш-объекта и возобновлению цикла предварительной загрузки.

Я попытался прослушать $ routeChangeStart, чтобы сделать protectDefault:

$scope.$on "$routeChangeStart", (ev,next,current) ->
  ev.preventDefault()
$scope.$on "$routeChangeSuccess", (ev,current) ->
  ev.preventDefault()

но безрезультатно. Если бы я мог найти способ переопределить перезагрузку представления, то изменил бы $ location.path.

Я все еще очень хорошо разбираюсь в AngularJS, поэтому буду рад любым советам о том, как структурировать приложение для достижения моей цели!

6 ответов

Решение

Вместо обновления пути, просто обновите параметр запроса с номером страницы.

установите ваш маршрут, чтобы игнорировать изменения параметров запроса:

....
$routeProvider.when('/foo', {..., reloadOnSearch: false})
....

и в обновлении вашего приложения $location с:

...
$location.search('page', pageNumber);
...

Из этого сообщения в блоге:

по умолчанию все изменения местоположения проходят процесс маршрутизации, который обновляет угловой вид.

Однако есть простой способ замкнуть это. Угловые часы для изменения местоположения (будь то путем ввода в строке местоположения, нажав ссылку или установив местоположение с помощью $location.path()). Когда он чувствует это изменение, он передает событие, $locationChangeSuccessи начинает процесс маршрутизации. Что мы делаем, это фиксируем событие и сбрасываем маршрут к тому, что было ранее.

function MyCtrl($route, $scope) {
    var lastRoute = $route.current;
    $scope.$on('$locationChangeSuccess', function(event) {
        $route.current = lastRoute;
    });
}

Мое решение состояло в том, чтобы использовать $ routeChangeStart, потому что это дает вам "следующий" и "последний" маршруты, вы можете сравнивать их без необходимости использования дополнительной переменной, как в $ locationChangeSuccess.

Преимущество заключается в возможности доступа к свойству "params" на "следующих" и "последних" маршрутах, таких как next.params.yourproperty когда вы используете стиль URL "/ property / value" и, конечно, используете $location.url или же $location.path изменить URL вместо $location.search() это зависит от стиля URL "? property = value".

В моем случае я использовал его не только для этого, но и для предотвращения изменения маршрута, если контроллер не изменился:

$scope.$on('$routeChangeStart',function(e,next,last){
  if(next.$$route.controller === last.$$route.controller){
    e.preventDefault();
    $route.current = last.$$route;
    //do whatever you want in here!
  }
});

Лично я чувствую, что AngularJS должен предоставить способ управления им, сейчас они предполагают, что всякий раз, когда вы меняете местоположение браузера, вы хотите изменить маршрут.

Вы должны быть загружены $location с помощью внедрения зависимостей и использования следующего:

$scope.apply(function () {
    $location.path("yourPath");
}

Имейте в виду, что вы не должны использовать хэштеги (#) при использовании $location.path, Это для совместимости для режима HTML5.

Мне нужно было сделать это, но после суеты, пытаясь получить $locationChange~ события, чтобы заставить его работать, я узнал, что вы можете сделать это на route с помощью resolve,

$routeProvider.when(
    '/page',
    {
        templateUrl : 'partial.html',
        controller : 'PageCtrl',
        resolve : {
            load : ['$q', function($q) {
                var defer = $q.defer();

                if (/*you only changed the idea thingo*/)
                    //dont reload the view
                    defer.reject('');
                //otherwise, load the view
                else
                    defer.resolve();

                return defer.promise;
            }]
        }
    }
);

Событие $locationChangeSuccess является немного грубым, но я обнаружил, что проверка пути позволяет избежать перезагрузок страницы, когда шаблон пути маршрута не изменяется, но перезагружает страницу при переключении на другой шаблон маршрута:

var lastRoute = $route.current;
$scope.$on('$locationChangeSuccess', function (event) {
    if (lastRoute.$$route.originalPath === $route.current.$$route.originalPath) {
        $route.current = lastRoute;
    }
});

Добавление этого кода к определенному контроллеру делает перезагрузку более интеллектуальной.

Редактировать: хотя это немного облегчает задачу, мне, в конечном счете, не понравилась сложность кода, который я писал, чтобы сохранить дружественные ссылки. В конце концов, я просто переключился на параметр поиска, и угловая работа с ним намного лучше.

С AngularJS V1.7.1,$route добавляет поддержку reloadOnUrl вариант конфигурации.

Если маршрут /foo/:id имеет reloadOnUrl знак равно false установить, затем перейти от /foo/id1 к /foo/id2 транслирует только $routeUpdate событие, и не перезагружает представление и повторно создает экземпляр контроллера.

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