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

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

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


当前回答

有点晚了,但我已经尝试了所有可能的方法,没有一个能正常工作。以下是我的优雅解决方案:

我使用一个控制器来管理我所有的页面与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');
       });
    });
});

所有可能的方法我都试过了,这个方法效果最好。

其他回答

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

它会滚动到列表的顶部

有点晚了,但我已经尝试了所有可能的方法,没有一个能正常工作。以下是我的优雅解决方案:

我使用一个控制器来管理我所有的页面与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');
       });
    });
});

所有可能的方法我都试过了,这个方法效果最好。

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

解决方案是在你的ngView元素中添加autoscroll="true":

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

经过一两个小时的尝试,ui-view autoscroll=true, $stateChangeStart, $locationChangeStart, $uiViewScrollProvider.useAnchorScroll(), $提供('$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');
})

以上所有答案都打破了预期的浏览器行为。大多数人想要的是,如果这是一个“新”页面,它会滚动到顶部,但如果你通过后退(或前进)按钮到达那里,它会返回到之前的位置。

如果你采用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;
}

它的工作方式是,路由器假设它要滚动到顶部,但会延迟一点,让浏览器有机会完成。如果浏览器随后通知我们更改是由于后退/前进导航,它将取消超时,并且滚动永远不会发生。

我使用原始文档命令来滚动,因为我想移动到窗口的整个顶部。如果你只是想让你的ui视图滚动,那么设置autoscroll="my_var",你可以使用上面的技术控制my_var。但我认为大多数人会想滚动整个页面,如果你去“新的”页面。

上面使用的是ui-router,不过你也可以使用ng-route,把$routeChangeSuccess换成$stateChangeSuccess。