Изменение маршрута не прокручивается вверху на новой странице

Я обнаружил какое-то нежелательное, по крайней мере для меня, поведение при изменении маршрута. На шаге 11 учебника http://angular.github.io/angular-phonecat/step-11/app/#/phones вы можете увидеть список телефонов. Если вы пролистаете нижнюю часть и нажимаете на одну из последних, вы можете видеть, что свиток не наверху, а скорее посередине.

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

Итак, есть ли элегантный способ прокрутки вверху при изменении маршрута?

Ответ 1

Проблема в том, что ваш ngView сохраняет позицию прокрутки, когда загружает новое представление. Вы можете указать $anchorScroll "прокрутить окно просмотра после обновления представления" (docs немного расплывчаты, но прокрутка здесь означает прокрутку до верхний нового представления).

Решение состоит в добавлении autoscroll="true" к элементу ngView:

<div class="ng-view" autoscroll="true"></div>

Ответ 2

Просто запустите этот код

$rootScope.$on("$routeChangeSuccess", function (event, currentRoute, previousRoute) {

    window.scrollTo(0, 0);

});

Ответ 3

Этот код отлично подойдет для меня.. Надеюсь, он также отлично подойдет вам. Все, что вам нужно сделать, это просто вставить $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()

и теперь вы можете увидеть, что свиток начинается сверху с новым маршрутизированным представлением:)

Ответ 4

После часа или двух попыток каждой комбинации 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');
})

Ответ 5

Вот мое (казалось бы) надежное, полное и (справедливо) сжатое решение. Он использует стиль, совместимый с миниатюрами (и доступ к вашему модулю angular.module(NAME)).

angular.module('yourModuleName').run(["$rootScope", "$anchorScroll" , function ($rootScope, $anchorScroll) {
    $rootScope.$on("$locationChangeSuccess", function() {
                $anchorScroll();
    });
}]);

PS Я обнаружил, что объект autoscroll не имел никакого эффекта, установлен ли true или false.

Ответ 6

Используя угловой UI Router, я делаю следующее:

    .state('myState', {
        url: '/myState',
        templateUrl: 'app/views/myState.html',
        onEnter: scrollContent
    })

С

var scrollContent = function() {
    // Your favorite scroll method here
};

Он никогда не сбой на какой-либо странице, и он не является глобальным.

Ответ 7

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

Ответ 8

вы можете использовать этот javascript

$anchorScroll()

Ответ 9

Если вы используете ui-router, вы можете использовать (при запуске)

$rootScope.$on("$stateChangeSuccess", function (event, currentState, previousState) {
    $window.scrollTo(0, 0);
});

Ответ 10

Я нашел это решение. Если вы перейдете к новому представлению, функция будет выполнена.

var app = angular.module('hoofdModule', ['ngRoute']);

    app.controller('indexController', function ($scope, $window) {
        $scope.$on('$viewContentLoaded', function () {
            $window.scrollTo(0, 0);
        });
    });

Ответ 11

Установка 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();
}]);

Ответ 12

Все приведенные выше ответы нарушают ожидаемое поведение браузера. То, что большинство людей хочет, это то, что прокрутит вверх, если это "новая" страница, но вернитесь в предыдущую позицию, если вы добираетесь туда через кнопку "Назад" (или "вперед" ).

Если вы предполагаете режим 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.

Ответ 13

Немного поздно вечеринке, но я пробовал все возможные методы, и ничего не работало правильно. Вот мое изящное решение:

Я использую контроллер, который управляет всеми моими страницами с помощью 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');
       });
    });
});

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

Ответ 14

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

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>

Ответ 16

Наконец-то я получил то, что мне нужно.

Мне нужно было прокрутить вверх, но хотелось переходов не

Вы можете контролировать это на уровне маршрута маршрута.
Я совмещаю вышеуказанное решение с помощью @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!
})

Ответ 17

Это сработало для меня, включая автопрокрутку

<div class="ngView" autoscroll="true" >

Ответ 18

Простое решение, добавьте scrollPositionRestoration в основной модуль маршрута включен.
Как это:

const routes: Routes = [

 {
   path: 'registration',
   loadChildren: () => RegistrationModule
},
];

 @NgModule({
  imports: [
   RouterModule.forRoot(routes,{scrollPositionRestoration:'enabled'})
  ],
 exports: [
 RouterModule
 ]
 })
  export class AppRoutingModule { }