3

我需要在页面重新加载时滚动到特定的锚标记。我尝试使用 $anchorScroll 但它评估 $location.hash(),这不是我需要的。

我根据 $anchorScrollProvider 的源代码编写了一个自定义提供程序。在其中,它向 rootScope 的 $watch 列表添加一个值,并在更改时调用 $evalAsync。

提供者:

zlc.provider('scroll', function() {
  this.$get = ['$window', '$rootScope', function($window, $rootScope) {
    var document = $window.document;
    var elm;

    function scroll() {
      elm = document.getElementById($rootScope.trendHistory.id);
      if (elm) elm.scrollIntoView();  
    }

    $rootScope.$watch(function scrollWatch() {return $rootScope.trendHistory.id;},
      function scrollWatchAction() {
        if ($rootScope.trendHistory.id) $rootScope.$eval(scroll);
      });

    return scroll;
  }];
});

现在,当我尝试在控制器中调用滚动提供程序时,我必须在调用 scroll() 之前使用 $scope.$apply() 强制执行摘要:

控制器:

//inside function called on reload
$scope.apply();
scroll();

为什么我必须调用 $scope.$apply()?为什么在当前范围内调用时,滚动函数不在 Angular 上下文中进行评估?谢谢您的帮助!

4

1 回答 1

2

我不确定您使用的想法是什么$rootScope.$eval(scroll)- 因为该scroll()函数已经在可以直接访问$rootScope.

如果我理解正确,您希望能够滚动到存储在$rootScope.trendHistory.id.

当该 id 更改时,您希望滚动到该元素(如果它存在于页面上)。

假设这是对您要实现的目标的正确解释,以下是我可能会如何实施它:

app.service('scrollService', function($rootScope) {
  $rootScope.trendHistory = {};

  $rootScope.$watch('trendHistory.id', function(val) {
    if (val) {
      elm = document.getElementById($rootScope.trendHistory.id);
      if (elm) elm.scrollIntoView();
    }
  });

  this.scrollTo = function(linkId) {
    $rootScope.trendHistory.id = linkId;
  }
});

这是一项服务(类似于您的提供者,但使用更简单的“服务”方法),它将在 $rootScope 上设置 $watch,查找对$rootScope.trendHistory.id. 当检测到更改时,它会滚动到指示的元素(如果存在) - 该位直接取自您的代码。

因此,要在控制器中使用它,您需要注入scrollService然后scrollTo()以 ID 作为参数调用它的方法。例子:

app.controller('AppController', function($scope, scrollService) {

        scrollService.scrollTo('some_id');

});

在您的问题中,您提到这需要在重新加载时发生,因此您只需将调用放入您的重新加载处理程序。您也可以直接$rootScope.trendHistory.id从应用程序中的任何位置修改 的值,它也会尝试滚动。

这是一个演示基本方法的演示:http ://plnkr.co/edit/cJpHoSemj2Z9muCQVKmj?p=preview

希望对您有所帮助,如果我误解了您的要求,我们深表歉意。

于 2014-08-27T12:44:12.930 回答