更改路线不会滚动到新页面的顶部

我发现了一些不受欢迎的,至less对我来说,路线改变时的行为。 在教程http://angular.github.io/angular-phonecat/step-11/app/#/phones的第11步中,您可以看到电话列表。 如果您滚动到底部并点击最新的一个,您可以看到滚动不在顶部,而是在中间。

我也在我的一个应用程序中发现了这一点,我想知道如何才能让它滚动到顶部。 我可以做的手工,但我认为应该有其他优雅的方式来做到这一点,我不知道。

那么,当路线改变时,是否有一种优雅的方式可以滚动到顶部?

问题是你的ngView在加载一个新视图的时候保留了滚动位置。 您可以指示$anchorScroll “在更新视图后滚动视口”( 文档有点含糊,但在此处滚动意味着滚动到新视图的顶部 )。

解决的办法是将autoscroll autoscroll="true"添加到你的ngView元素中:

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

只要把这个代码运行

 $rootScope.$on("$routeChangeSuccess", function (event, currentRoute, previousRoute) { window.scrollTo(0, 0); }); 

在尝试ui-view autoscroll=true$stateChangeStart$locationChangeStart$uiViewScrollProvider.useAnchorScroll()$provide('$uiViewScroll', ...)和其他许多组合的一两个小时后,不要让页面滚动到页面顶部按预期工作。

这最终是为我工作的。 它捕获pushState和replaceState,并且只有当新页面被导航到(后退/前进button保持其滚动位置)时才更新滚动位置:

 .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'); }) 

这段代码对我来说很好,我希望它也能为你工作。所有你需要做的只是注入$ anchorScroll到你的运行块,并应用监听function到rootScope,就像我在下面的例子中所做的那样。

  angular.module('myAngularApp') .run(function($rootScope, Auth, $state, $anchorScroll){ $rootScope.$on("$locationChangeSuccess", function(){ $anchorScroll(); }); 

这里是Angularjs模块的调用顺序:

  1. app.config()
  2. app.run()
  3. directive's compile functions (if they are found in the dom)
  4. app.controller()
  5. directive's link functions (again, if found)

RUN BLOCK在注入器创build后被执行,用于启动应用程序..这意味着当你redirect到新的路由视图时,运行块中的监听器调用

$ anchorScroll()

你现在可以看到滚动开始到新的路由视图的顶部:)

这是我(似乎)强大,完整和(相当)简洁的解决scheme。 它使用缩小兼容样式(和模块的angular.module(NAME)访问)。

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

PS我发现,无论是设置为true还是false,autoscroll的东西都没有影响。

使用angularjs UI路由器,我正在做的是这样的:

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

附:

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

它在任何页面上都不会失败,并且不是全局的。

仅供参考标题中描述的问题(正如我所做的),谁也使用AngularUI路由器插件的FYI

正如在这个问题中提出并回答的那样,当您更改路由时,angular-ui路由器将跳转到页面的底部。
不知道为什么页面加载在底部? Angular UI-Router自动滚动问题

但是,正如答案所述,您可以通过在您的ui-view上说autoscroll="false"来closures此行为。

例如:

 <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

你可以使用这个JavaScript

 $anchorScroll() 

如果你使用ui-router,你可以使用(运行时)

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

我发现这个解决scheme。 如果你去一个新的视图的function得到执行。

 var app = angular.module('hoofdModule', ['ngRoute']); app.controller('indexController', function ($scope, $window) { $scope.$on('$viewContentLoaded', function () { $window.scrollTo(0, 0); }); }); 

设置autoScroll为true并不是我的诡计,所以我确实select了另一个解决scheme。 我构build了一个服务,每次更改路由时都会挂钩,并使用内置的$ 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(); }]); 

上面的所有答案都打破了预期的浏览器行为。 大多数人所需要的是如果它是“新”页面将滚动到顶部的东西,但如果通过“后退”(或“前进”)button返回到前一个位置,则返回到前一个位置。

如果你假定使用HTML5模式,事实certificate这很容易(虽然我相信一些明智的人可以弄清楚如何使这更优雅!):

 // 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; } 

它的工作方式是路由器假定它将滚动到顶部,但延迟一点让浏览器有机会完成。 如果浏览器然后通知我们该更改是由于后退/前进导航导致的,则取消超时,并且不会出现滚动。

我使用原始document命令滚动,因为我想移动到整个窗口的顶部。 如果你只是想要你的ui-view滚动,然后设置autoscroll="my_var"在哪里你控制my_var使用上述技术。 但我想大多数人会想要滚动整个页面,如果你要去“新”页面。

上面使用的是ui-router,不过你可以用ng-route代替$stateChangeSuccess $routeChangeSuccess

晚会有点晚,但我已经尝试了所有可能的方法,没有任何工作正确。 这是我优雅的解决scheme:

我用一个控制器来pipe理我的所有页面与ui路由器。 它允许我将未经身份validation或validation的用户redirect到适当的位置。 大多数人把他们的中间件放在他们应用程序的configuration中,但是我需要一些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'); }); }); }); 

我尝试了所有可能的select,这种方法效果最好。

没有提供的答案解决了我的问题。 我使用视图之间的animation和滚动将始终发生在animation之后。 我find的解决scheme,以便animation之前滚动到顶部是以下指令:

 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> 

试试这个http://ionicframework.com/docs/api/service/ $ ionicScrollDelegate /

它滚动到列表的顶部scrollTop()