Я обнаружил какое-то нежелательное, по крайней мере для меня, поведение при изменении маршрута. На шаге 11 учебника http://angular.github.io/angular-phonecat/step-11/app/#/phones вы можете увидеть список телефонов. Если вы пролистаете нижнюю часть и нажимаете на одну из последних, вы можете видеть, что свиток не наверху, а скорее посередине.
Я тоже нашел это в одном из моих приложений, и мне было интересно, как это сделать, чтобы прокрутить вверх. Я могу сделать это на людях, но я думаю, что должен быть другой элегантный способ сделать это, чего я не знаю.
Итак, есть ли элегантный способ прокрутки вверху при изменении маршрута?
Проблема в том, что ваш ngView сохраняет позицию прокрутки, когда загружает новое представление. Вы можете указать $anchorScroll
"прокрутить окно просмотра после обновления представления" (docs немного расплывчаты, но прокрутка здесь означает прокрутку до верхний нового представления).
Решение состоит в добавлении autoscroll="true"
к элементу ngView:
<div class="ng-view" autoscroll="true"></div>
Просто запустите этот код
$rootScope.$on("$routeChangeSuccess", function (event, currentRoute, previousRoute) {
window.scrollTo(0, 0);
});
$window.scrollTop(0,0)
работает для меня лучше, чем автопрокрутка. В моем случае у меня есть представления, которые входят и выходят с переходами.
Этот код отлично подойдет для меня.. Надеюсь, он также отлично подойдет вам. Все, что вам нужно сделать, это просто вставить $anchorScroll в ваш блок выполнения и применить функцию прослушивателя к корневому объекту, как я сделал в приведенном ниже примере.
angular.module('myAngularApp')
.run(function($rootScope, Auth, $state, $anchorScroll){
$rootScope.$on("$locationChangeSuccess", function(){
$anchorScroll();
});
Здесь порядковый номер модуля Angularjs:
app.config()
app.run()
directive compile functions (if they are found in the dom)
app.controller()
directive link functions (again, if found)
RUN BLOCK выполняются после создания инжектора и используются для запуска приложения. Это означает, что при перенаправлении на новое представление маршрута слушатель в блоке запуска вызывает
$anchorScroll()
и теперь вы можете увидеть, что свиток начинается сверху с новым маршрутизированным представлением:)
После часа или двух попыток каждой комбинации ui-view autoscroll=true
, $stateChangeStart
, $locationChangeStart
, $uiViewScrollProvider.useAnchorScroll()
, $provide('$uiViewScroll', ...)
и многих других я не смог получить свиток к вершине, новая страница работает должным образом.
В конечном итоге это помогло мне. Он захватывает pushState и replaceState и обновляет положение прокрутки при навигации по новым страницам (кнопка назад/вперед сохраняет позиции прокрутки):
.run(function($anchorScroll, $window) {
// hack to scroll to top when navigating to new URLS but not back/forward
var wrap = function(method) {
var orig = $window.window.history[method];
$window.window.history[method] = function() {
var retval = orig.apply(this, Array.prototype.slice.call(arguments));
$anchorScroll();
return retval;
};
};
wrap('pushState');
wrap('replaceState');
})
$locationProvider.html5Mode(true);
@wkronkel, есть ли способ сделать это, когда не используется режим HTML5 в angular? Причина перезагрузки страницы выдает 404 ошибки из-за активного режима HTML 5
Вот мое (казалось бы) надежное, полное и (справедливо) сжатое решение. Он использует стиль, совместимый с миниатюрами (и доступ к вашему модулю angular.module(NAME)).
angular.module('yourModuleName').run(["$rootScope", "$anchorScroll" , function ($rootScope, $anchorScroll) {
$rootScope.$on("$locationChangeSuccess", function() {
$anchorScroll();
});
}]);
PS Я обнаружил, что объект autoscroll не имел никакого эффекта, установлен ли true или false.
Используя угловой UI Router, я делаю следующее:
.state('myState', {
url: '/myState',
templateUrl: 'app/views/myState.html',
onEnter: scrollContent
})
С
var scrollContent = function() {
// Your favorite scroll method here
};
Он никогда не сбой на какой-либо странице, и он не является глобальным.
onEnter: scrollContent
// Your favorite scroll method here
?
FYI для тех, кто сталкивается с проблемой, описанной в названии (как и я), который также использует AngularUI Router плагин...
Как было задано и ответили в этом вопросе SO, маршрутизатор angular -ui перескакивает в нижнюю часть страницы при изменении маршрутов.
Не могу понять, почему страница загружается внизу? Angular Ошибка автопрокрутки UI-маршрутизатора
Однако, как говорится в ответе, вы можете отключить это поведение, сказав autoscroll="false"
на ui-view
.
Например:
<div ui-view="pagecontent" autoscroll="false"></div>
<div ui-view="sidebar" autoscroll="false"></div>
http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.directive:ui-view
Если вы используете ui-router, вы можете использовать (при запуске)
$rootScope.$on("$stateChangeSuccess", function (event, currentState, previousState) {
$window.scrollTo(0, 0);
});
вы можете использовать этот javascript
$anchorScroll()
Я нашел это решение. Если вы перейдете к новому представлению, функция будет выполнена.
var app = angular.module('hoofdModule', ['ngRoute']);
app.controller('indexController', function ($scope, $window) {
$scope.$on('$viewContentLoaded', function () {
$window.scrollTo(0, 0);
});
});
Установка autoScroll в true не помогло мне, поэтому я выбрал другое решение. Я построил службу, которая перехватывает каждый раз, когда изменяется маршрут, и который использует встроенную службу $anchorScroll для прокрутки вверх. Работает для меня: -).
Услуги:
(function() {
"use strict";
angular
.module("mymodule")
.factory("pageSwitch", pageSwitch);
pageSwitch.$inject = ["$rootScope", "$anchorScroll"];
function pageSwitch($rootScope, $anchorScroll) {
var registerListener = _.once(function() {
$rootScope.$on("$locationChangeSuccess", scrollToTop);
});
return {
registerListener: registerListener
};
function scrollToTop() {
$anchorScroll();
}
}
}());
Регистрация:
angular.module("mymodule").run(["pageSwitch", function (pageSwitch) {
pageSwitch.registerListener();
}]);
Ни один из предоставленных ответов не разрешил мою проблему. Я использую анимацию между представлениями, и прокрутка всегда будет происходить после анимации. Решение, которое я нашел так, что прокрутка вверху происходит до анимации, является следующей директивой:
yourModule.directive('scrollToTopBeforeAnimation', ['$animate', function ($animate) {
return {
restrict: 'A',
link: function ($scope, element) {
$animate.on('enter', element, function (element, phase) {
if (phase === 'start') {
window.scrollTo(0, 0);
}
})
}
};
}]);
Я вставил его на мой взгляд следующим образом:
<div scroll-to-top-before-animation>
<div ng-view class="view-animation"></div>
</div>
Немного поздно вечеринке, но я пробовал все возможные методы, и ничего не работало правильно. Вот мое изящное решение:
Я использую контроллер, который управляет всеми моими страницами с помощью ui-router. Это позволяет мне перенаправлять пользователей, которые не прошли проверку подлинности или не были проверены в соответствующем месте. Большинство людей помещают свое промежуточное ПО в свою конфигурацию приложения, но мне нужны некоторые HTTP-запросы, поэтому глобальный контроллер работает лучше для меня.
Мой index.html выглядит так:
<main ng-controller="InitCtrl">
<nav id="top-nav"></nav>
<div ui-view></div>
</main>
Мой initCtrl.js выглядит так:
angular.module('MyApp').controller('InitCtrl', function($rootScope, $timeout, $anchorScroll) {
$rootScope.$on('$locationChangeStart', function(event, next, current){
// middleware
});
$rootScope.$on("$locationChangeSuccess", function(){
$timeout(function() {
$anchorScroll('top-nav');
});
});
});
Я пробовал все возможные варианты, этот метод работает наилучшим образом.
id="top-nav"
на правильный элемент.
Все приведенные выше ответы нарушают ожидаемое поведение браузера. То, что большинство людей хочет, это то, что прокрутит вверх, если это "новая" страница, но вернитесь в предыдущую позицию, если вы добираетесь туда через кнопку "Назад" (или "вперед" ).
Если вы предполагаете режим HTML5, это оказывается легким (хотя я уверен, что некоторые яркие люди там могут понять, как сделать это более элегантным!):
// Called when browser back/forward used
window.onpopstate = function() {
$timeout.cancel(doc_scrolling);
};
// Called after ui-router changes state (but sadly before onpopstate)
$scope.$on('$stateChangeSuccess', function() {
doc_scrolling = $timeout( scroll_top, 50 );
// Moves entire browser window to top
scroll_top = function() {
document.body.scrollTop = document.documentElement.scrollTop = 0;
}
Как это работает, маршрутизатор предполагает, что он будет прокручиваться вверх, но немного задерживается, чтобы дать браузеру возможность закончить. Если браузер уведомляет нас о том, что изменение произошло из-за навигации "Назад/Вперед", оно отменяет тайм-аут, и прокрутка никогда не возникает.
Я использовал команды raw document
для прокрутки, потому что я хочу перейти ко всей вершине окна. Если вы просто хотите, чтобы ваш ui-view
прокручивался, установите autoscroll="my_var"
, где вы управляете my_var
, используя вышеприведенные методы. Но я думаю, что большинство людей захотят прокрутить всю страницу, если вы переходите на страницу как "новое".
В приведенном выше примере используется ui-router, но вместо этого вы можете использовать ng-route, заменив $routeChangeSuccess
на $stateChangeSuccess
.
var routerApp = angular.module('routerApp', ['ui.router']); routerApp.config(function($stateProvider, $urlRouterProvider, $locationProvider) { $urlRouterProvider.otherwise('/home'); $locationProvider.html5Mode(false).hashPrefix(""); $stateProvider // HOME STATES AND NESTED VIEWS ======================================== .state('home', { url: '/home', templateUrl: 'partial-home.html' }) });
Простое решение, добавьте scrollPositionRestoration
в основной модуль маршрута включен.
Как это:
const routes: Routes = [
{
path: 'registration',
loadChildren: () => RegistrationModule
},
];
@NgModule({
imports: [
RouterModule.forRoot(routes,{scrollPositionRestoration:'enabled'})
],
exports: [
RouterModule
]
})
export class AppRoutingModule { }
Это сработало для меня, включая автопрокрутку
<div class="ngView" autoscroll="true" >
Наконец-то я получил то, что мне нужно.
Мне нужно было прокрутить вверх, но хотелось переходов не
Вы можете контролировать это на уровне маршрута маршрута.
Я совмещаю вышеуказанное решение с помощью @wkonkel и добавляю простой параметр noScroll: true
к некоторым объявлениям маршрута. Тогда я поймаю это на переходе.
В целом: это всплывает в верхней части страницы на новых переходах, оно не плавает вверху на переходах Forward
/Back
, и это позволяет вам переопределить это поведение, если это необходимо.
Код: (предыдущее решение плюс дополнительная опция noScroll)
// hack to scroll to top when navigating to new URLS but not back/forward
let wrap = function(method) {
let orig = $window.window.history[method];
$window.window.history[method] = function() {
let retval = orig.apply(this, Array.prototype.slice.call(arguments));
if($state.current && $state.current.noScroll) {
return retval;
}
$anchorScroll();
return retval;
};
};
wrap('pushState');
wrap('replaceState');
Поместите это в блок app.run
и введите $state
... myApp.run(function($state){...})
Затем, если вы не хотите прокручивать верхнюю часть страницы, создайте такой маршрут:
.state('someState', {
parent: 'someParent',
url: 'someUrl',
noScroll : true // Notice this parameter here!
})
Попробуйте http://ionicframework.com/docs/api/service/ $ionicScrollDelegate/
Он прокручивается до верхней части списка scrollTop()
<div class="ng-view" autoscroll></div>
и он будет работать точно так же (если вы не хотите сделать прокрутку условной).