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
событие, и не перезагружает представление и повторно создает экземпляр контроллера.