一尘不染

AngularJS指令滚动到给定项目

angularjs

我有一个在我的控制器中定义的范围变量$ scope.first_unread_id。在我的模板中,我有:

<div id="items" >
  <ul class="standard-list">
    <li ng-repeat="item in items" scroll-to-id="first_unread_id">
    <span class="content">{{ item.content }}</span>
    </li>
  </ul>
</div>

和我的指令看起来像:

angular.module('ScrollToId', []).
directive('scrollToId', function () {
  return function (scope, element, attributes) {
    var id = scope.$parent[attributes["scrollToId"]];
    if (id === scope.item.id) {
      setTimeout(function () {
        window.scrollTo(0, element[0].offsetTop - 100)
      }, 20);
    }
  }

});

它起作用,但是,有两个问题:

  1. 有没有比查询范围。$ parent更好的方法来将“ first_unread_id”从控制器范围内移到直接范围内?这似乎有点“棘手”。我希望我可以将它作为唯一的参数传递给直接视图,而不必在任何li元素上重复。

  2. 有没有更好的方法来避免需要setTimeout()调用?没有它,它 有时会 起作用-我想是由于布局时间的差异。我知道我使用的语法定义了链接功能-但我不清楚默认情况下该链接是前置链接还是后置链接-甚至对我的问题来说也很重要。


阅读 226

收藏
2020-07-04

共1个答案

一尘不染

  1. 您不需要scope。$ parent-因为它将从父范围继承该值,并且当它在父范围中更改时,它将被向下传递。
  2. 默认值为后链接功能。您是否有一些图像或加载的东西会使初始加载后不久的页面布局发生变化?您是否尝试了没有时间的setTimeout,例如setTimeout(function(){})?这样可以确保在完成所有其他操作之后,可以“一次执行”。
  3. 我还将稍微更改您的指令的逻辑以使其更通用。如果给定条件为真,我将其滚动到该元素。

这是这3项更改:

的HTML:

<div id="items" >
  <ul class="standard-list">
    <li ng-repeat="item in items" scroll-if="item.id == first_unread_id">
      <span class="content">{{ item.content }}</span>
    </li>
  </ul>
</div>

JS:

app.directive('scrollIf', function () {
  return function (scope, element, attributes) {
    setTimeout(function () {
      if (scope.$eval(attributes.scrollIf)) {
        window.scrollTo(0, element[0].offsetTop - 100)
      }
    });
  }
});
2020-07-04