用于滚动到给定项目的 AngularJS 指令 [英] AngularJS directive to scroll to a given item

查看:25
本文介绍了用于滚动到给定项目的 AngularJS 指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

<ul class="标准列表"><li ng-repeat="item in items" scroll-to-id="first_unread_id"><span class="content">{{ item.content }}</span>

我的指令看起来像:

angular.module('ScrollToId', []).指令('scrollToId',函数(){返回函数(范围、元素、属性){var id = scope.$parent[attributes["scrollToId"]];if (id === scope.item.id) {设置超时(函数(){window.scrollTo(0, element[0].offsetTop - 100)}, 20);}}});

它有效,但是有两个问题:

  1. 是否有比询问 scope.$parent 更好的方法将控制器作用域中的first_unread_id"引入直接?这似乎有点恶心".我希望我可以通过视图将它作为参数传递给直接,而不必在 li 元素上重复.

  2. 有没有更好的方法来避免调用 setTimeout() 的需要?没有它,它有时就可以工作——我想是由于布局时间的不同.我知道我使用的语法是定义链接函数 - 但我不清楚默认情况下这是前链接还是后链接 - 以及这是否对我的问题很重要.

解决方案

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

以下是这 3 个更改:

html:

<ul class="标准列表"><li ng-repeat="item in items" scroll-if="item.id == first_unread_id"><span class="content">{{ item.content }}</span>

JS:

app.directive('scrollIf', function () {返回函数(范围、元素、属性){设置超时(函数(){if (scope.$eval(attributes.scrollIf)) {window.scrollTo(0, element[0].offsetTop - 100)}});}});

I have a scope variable $scope.first_unread_id which is defined in my controller. In my template, I have:

<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>

and my directive looks like:

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

});

it works, however, two questions:

  1. Is there a better way of getting the "first_unread_id" off the controller scope into the direct than interrogating scope.$parent? This seems a bit 'icky'. I was hoping I could pass that through the view to the direct as a parameter w/o having to repeat that on ever li element.

  2. Is there a better way to avoid the need of the setTimeout() call? Without it, it works sometimes - I imagine due to difference in timing of layout. I understand the syntax I have used is defining a link function - but it isn't clear to me if that is a pre or post-link by default - and if that even matters for my issue.

解决方案

  1. You shouldn't need the scope.$parent - since it will inherit the value from the parent scope, and when it changes in the parent scope it will be passed down.
  2. The default is a post-link function. Do you have some images or something loading that would make the page layout change shortly after initial load? Have you tried a setTimeout with no time on it, eg setTimeout(function(){})? This would make sure this would go 'one after' everything else is done.
  3. I would also change the logic of your directive a bit to make it more general. I would make it scroll to the element if a given condition is true.

Here are those 3 changes:

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

这篇关于用于滚动到给定项目的 AngularJS 指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆