【问题标题】:Why does the if and else both get executed on scroll?为什么 if 和 else 都在滚动时执行?
【发布时间】:2015-09-07 01:03:51
【问题描述】:

我的滚动事件出现了这种非常奇怪的行为,我似乎无法弄清楚为什么会发生这种情况或如何解决它。基本上我所拥有的是一个监听滚动的事件侦听器,但是 if 和 else 都在滚动时执行..

我得到了这个指令:

core.directive('offsetColor', [function() {

  return {
    restrict: 'A',
    link: function(scope, element, attrs) {

      $window.on('scroll', function() {
        var windowY = $(window).scrollTop();
        var elementY = element.offset().top - 60; // -60 to add site header height

        if (elementY <= windowY) {
          console.log('element is at top');
        }
        else {
          console.log('no element is at top');
        }
      });
    }
  }
}]);

谁的任务是根据某些元素的 y 位置更改站点标题的颜色。

目前我已经在两个元素上设置了这个指令。

现在我对为什么会发生这种情况的简单猜测是因为我在 两个 元素而不是 一个 上设置了指令,因此滚动事件“循环”通过这两个元素元素并检查它们的 y 位置。所以其中一个元素在顶部,而另一个不在顶部,导致 ifelse 都被执行。

我觉得我已经尝试了一切来阻止它同时执行,但我没有找到解决方案。

我在这里做错了什么?

【问题讨论】:

  • 你可能需要一个外部范围变量来同步两个对象,所以如果一个去如果另一个不去
  • 您的简单猜测似乎是正确的。两个 window.onscroll 处理程序将竞争,一个(最后一个附加的)将确定标题的颜色。您需要的是 一个 window.onscroll 处理程序,它读取所有相关元素的位置并根据您想要的任何规则确定标题的颜色。
  • @Roamer-1888 关于如何实现这一点的任何建议?
  • 不是真的,因为我不理解 core.directive() 包装器或 restrict 的含义。在原始 jQuery 中,您只需将 $window.on('scroll', ...) 包装在 $.(function() {...}) 中。
  • @Chrillewoodz 您可以将逻辑放在一个父指令中,而不是元素本身的多个指令。请参阅下面的答案以获取示例。

标签: jquery angularjs scroll angular-directive


【解决方案1】:

正如 cmets 中提到的 Roamer-1888,为了解决此类问题,您需要整合事件处理程序(在本例中为滚动侦听器)。

这里有一个想法:创建一个指令并将其应用于所有更改标题颜色的元素的共同祖先。在该指令内的窗口上添加滚动监听器。

现在,无论是使用 jQuery,还是使用与父指令 (like the AngularJS tabs example) 对话的子指令,循环遍历所有可能更改标题颜色的元素。从窗口位置获取它们的偏移量,然后找到偏移量最小的那个。

偏移量最小的元素是应该影响标题颜色的元素。

总而言之,你的指令看起来像这样(走 jQuery 路线;嵌套指令路线留给阅读练习)(未经测试):

core.directive('offsetColorContainer', [function() {

  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
      var colorElems = $('.some-selector-that-identifies-your-color-elems', element);

      $window.on('scroll', function() {
        var windowY = $(window).scrollTop(),
            closestElem = null,
            closestDist = null;

        colorElems.each(function() {
          var elem = $(this),
              elemDist = Math.abs(elem.offset().top - windowY);

          if (closestElem === null || elemDist < closestDist)
          {
            closestElem = elem;
            closestDist = elemDist;
          }
        });

        if (closestElem !== null)
        {
          // change the header color based on closestElem
        }
      });
    }
  }
}]);

请注意,您可能需要根据元素实际表示的内容来调整元素距离逻辑,但这应该能让您朝着正确的方向开始。

【讨论】:

  • 由于某种原因无法使每个循环工作,即使我有项目,它也不会通过 colorElems 中的元素。
  • 检查您的控制台并确保没有任何问题。放一些console.log 语句,或者,更好的是,使用JS 调试器。 .each() 应该可以正常工作。
  • 我有,除了每个都运行。
  • 好吧,.each() 调用必须正在运行,但它必须在一组空元素上运行。执行console.log(colorElems) 并查看它的输出。确保元素列表不为空。如果元素列表不为空,则.each() 调用肯定正在运行,但其中的某些内容肯定是错误的。在.each() 调用中添加console.log() 调用以找出答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-06
  • 2022-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-28
相关资源
最近更新 更多