Angularjs: 如何在div中滚动到滚动条底部时触发事件?

Angularjs: How to trigger event when scroll reaches to the bottom of the scroll bar in div?

我试图在滚动条到达末尾时触发一个事件。我找到了这个 this example。这是我的代码。问题是它根本不调用 loadmore() 。 控制台语句的值是:

848
899
in scroll
881
899
in scroll
892
899
in scroll
897
899
in scroll
900
899

好像从来没有到那个if语句!奇怪的是,如果我在 inspect element 中调试它,它就会触发事件。 ..... 我的指令:

directive('scrolly', function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            var raw = element[0];
            console.log('loading directive');
            element.bind('scroll', function () {
                console.log('in scroll');
                console.log(raw.scrollTop + raw.offsetHeight);
                console.log(raw.scrollHeight);
                if (raw.scrollTop + raw.offsetHeight == raw.scrollHeight) { //at the bottom
                    scope.$apply(attrs.scrolly);
                }
            })
        }
    }

请检查 if 语句中的左侧是否大于右侧,而不是检查是否相等,因为滚动条位于底部就是这种情况。

raw.scrollTop + raw.offsetHeight > raw.scrollHeight

这是工作 jsfiddle

我一直在寻找一个片段来帮助我做到这一点,但找不到任何有价值的东西,所以我想出了这个相当容易使用的指令来做到这一点

'use strict';
// Tested with Angular 1.3, 1.4.8
angular.module('scrollToEnd', [])
  /**
   * @ngdoc directive
   * @name scrollToEnd:scrollToEnd
   * @scope
   * @restrict A
   *
   * @description
   * Supply a handler to be called when this element is scrolled all the way to any extreme.
   * The callback must have the following signature:
   * void function (direction:'top'|'bottom'|'left'|'right')
   * If the `bindToWindow` attribute is truthy, the callback will be issued for the window
   * instead of the element that the directive is on.
   *
   * Example usage:
   * `<div scroll-to-end="scrollToEndWindow" bind-to-window="true">`
   * This will call the controller's `scrollToEndWindow` function whenever the window reaches
   * the edges when scrolling. If the div itself is a scrollable element for which the
   * handler should be called instead, remove the bind-to-window attribute entirely.
   *
   * @param {function}  emScrollToEnd   Callback to be invoked
   * @param {boolean}       bindToWindow        Bind to the window instead of the element
   *
   */
  .directive('scrollToEnd', function ($window) {
    // Get the specified element's computed style (height, padding, etc.) in integer form
    function getStyleInt(elem, prop) {
      try {
        return parseInt(window.getComputedStyle(elem, null).getPropertyValue(prop), 10);
      } catch (e) {
        return parseInt(elem.currentStyle[prop], 10);
      }
    }

    // Get the 'innerHeight' equivalent for a non-window element, including padding
    function getElementDimension(elem, prop) {
      switch (prop) {
        case 'width':
          return getStyleInt(elem, 'width') +
          getStyleInt(elem, 'padding-left') +
          getStyleInt(elem, 'padding-right');
        case 'height':
          return getStyleInt(elem, 'height') +
          getStyleInt(elem, 'padding-top') +
          getStyleInt(elem, 'padding-bottom');
        /*default:
          return null;*/
      }
    }
    return {
      restrict: 'A',
      scope: {
        callback: '=scrollToEnd'
      },
      link: function (scope, elem, attr) {
        var callback = scope.callback || function () {};
        var boundToWindow = attr.bindToWindow;
        var body = document.body;
        var html = document.documentElement;
        var boundElement = boundToWindow ? angular.element($window) : elem;
        var oldScrollX = 0;
        var oldScrollY = 0;
        var handleScroll = function () {
          // Dimensions of the content, including everything scrollable
          var contentWidth;
          var contentHeight;
          // The dimensions of the container with the scrolling, only the visible part
          var viewportWidth;
          var viewportHeight;
          // The offset of how much the user has scrolled
          var scrollX;
          var scrollY;

          if (boundToWindow) {
            // Window binding case - Populate Dimensions
            contentWidth = Math.max(
              body.scrollWidth,
              body.offsetWidth,
              html.clientWidth,
              html.scrollWidth,
              html.offsetWidth
            );
            contentHeight = Math.max(
              body.scrollHeight,
              body.offsetHeight,
              html.clientHeight,
              html.scrollHeight,
              html.offsetHeight
            );
            viewportWidth = window.innerWidth;
            viewportHeight = window.innerHeight;
            scrollX = (window.pageXOffset || html.scrollLeft) - (html.clientLeft || 0);
            scrollY = (window.pageYOffset || html.scrollTop) - (html.clientTop || 0);
          } else {
            // DOM element case - Populate Dimensions
            var domElement = boundElement[0];
            contentWidth = domElement.scrollWidth;
            contentHeight = domElement.scrollHeight;
            viewportWidth = getElementDimension(domElement, 'width');
            viewportHeight = getElementDimension(domElement, 'height');
            scrollX = domElement.scrollLeft;
            scrollY = domElement.scrollTop;
          }

          var scrollWasInXDirection = oldScrollX !== scrollX;
          var scrollWasInYDirection = oldScrollY !== scrollY;
          oldScrollX = scrollX;
          oldScrollY = scrollY;

          if (scrollWasInYDirection && scrollY === 0) {
            callback('top');
          } else if (scrollWasInYDirection && scrollY === contentHeight - viewportHeight) {
            callback('bottom');
          } else if (scrollWasInXDirection && scrollX === 0) {
            callback('left');
          } else if (scrollWasInXDirection && scrollX === contentWidth - viewportWidth) {
            callback('right');
          }
        };
        boundElement.bind('scroll', handleScroll);
        // Unbind the event when scope is destroyed
        scope.$on('$destroy', function () {
          boundElement.unbind('scroll', handleScroll);
        });
      }
    };
  });

https://gist.github.com/podrezo/f80f35d6d0655f4d550cac4747c110ff

这里有一个 jsfiddle 可供试用:

https://jsfiddle.net/va4x5r26/2/

适用于 Angular 1.3 和 1.4.8,并在 IE10 和 Chrome 55 上测试。

你给了我一些很好的提示......这是一个完整的工作示例,供任何偶然发现此问题的人使用 post:

JS:

app.controller("controller", function ($scope) {
    $scope.test = function () {
        alert("hello!");
    }
}

HTML:

<div class="br-section1" on-scroll-to-bottom="test()">
</div>

应用指令:

app.directive('onScrollToBottom', function ($document) {
    //This function will fire an event when the container/document is scrolled to the bottom of the page
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {

            var doc = angular.element($document)[0].body;

            $document.bind("scroll", function () {

                //console.log('in scroll');
                //console.log("scrollTop + offsetHeight:" + (doc.scrollTop + doc.offsetHeight));
                //console.log("scrollHeight: " + doc.scrollHeight);

                if (doc.scrollTop + doc.offsetHeight >= doc.scrollHeight) {
                    //run the event that was passed through
                    scope.$apply(attrs.onScrollToBottom);
                }
            });
        }
    };
});

当浏览器的滚动条向下移动时,我们需要触发一个事件。以下代码适用于 Angular 6.

 import { HostListener } from '@angular/core';
     @HostListener('window:scroll', ['$event'])
      onScroll(): void {
        if ((window.innerHeight + window.scrollY) >= (document.documentElement.scrollHeight - 1)) {
          // Place your code here
        }
      }

我采用了 Mark 的代码并进行了一些更改以添加对 div 元素的支持。 请注意,您可以定义另一个属性来配置阈值(在我的例子中为 50)。

angular.module('O2DigitalSite').directive('onScrollToBottom', function ($document) {
    //This function will fire an event when the container/document is scrolled to the bottom of the page
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            var ele = element[0];
            element.bind("scroll", function () {
                //console.log((ele.scrollTop + ele.offsetHeight) + " / " + (ele.scrollHeight));
                if (ele.scrollTop + ele.offsetHeight >= ele.scrollHeight - 50) {
                    //run the event that was passed through
                    scope.$apply(attrs.onScrollToBottom);
                }
            });
        }
    };
});