【问题标题】:AngularJS Server side pagination on mouse scroll directive event called twice两次调用鼠标滚动指令事件的AngularJS服务器端分页
【发布时间】:2015-04-19 17:27:49
【问题描述】:

我正在尝试在鼠标滚动事件上实现服务器端分页,以在滚动到页面/div 底部时加载数据。我做了一些研究,发现有很多选项可以做到这一点,比如 ngInfiniteScroll 等。

有了这个,我还发现了几个小提琴,它们在没有任何第三方 js 依赖的情况下做同样的事情,如下面的链接中提到的 -

AngularJS Server side pagination on mouse scroll

http://jsfiddle.net/akagr/Eu2FW/4/light/

http://jsfiddle.net/vojtiik/n2NHL/

我还通过引用最后一个链接(即http://jsfiddle.net/vojtiik/n2NHL/)创建了一个 POC,它在 POC 中也可以正常工作。

以下是我实现的 POC 代码。为了方便起见,我对其进行了一些修改,但概念是相同的:

Index.html 文件:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" data-ng-app="myApp">
<head>
    <title></title>
    <script src="Scripts/JS/angular.js"></script>
    <script src="Scripts/JS/angular.min.js"></script>
    <script src="Scripts/JS/jquery.min.js"></script>
    <script src="Scripts/ngInfiniteScroll/ng-infinite-scroll1.2.0.js"></script>
    <script src="Scripts/ngInfiniteScroll/ng-infinite-scroll1.2.0.min.js"></script>
    <script src="Scripts/JS/angular-route.min.js"></script>
    <script src="app/app.js"></script>
    <script src="app/Controllers/mainCtrl.js"></script>
    <style>
        li {
            height: 120px;
            border-bottom: 1px solid gray;
        }

        #fixed {
            height: 400px;
            overflow: auto;
        }
    </style>

</head>
<body data-ng-controller="mainCtrl">
    <div id="fixed" when-scrolled="loadMore()">
        <ul>
            <li ng-repeat="i in items">{{i.id}}</li>
        </ul>
    </div>
</body>
</html>

app.js 文件:

var myApp = angular.module('myApp', []);
myApp.directive('whenScrolled', function () {

    return function (scope, elm, attr) {
        var raw = elm[0];
        var takeRows = scope.takeRows;

        elm.bind('scroll', function () {
            if (raw.scrollTop + raw.offsetHeight >= raw.scrollHeight) {
                // scope.$apply(attr.whenScrolled({ id: takeRows }));
                scope.loadMore(takeRows);
                scope.$apply();
            }
        });
    };
});

mainCtrl.js

myApp.controller('mainCtrl', ['$scope', '$rootScope', function ($scope, $rootScope) {
    $scope.items = [];

    var counter = 0;
    $scope.takeRows = 20;

    $scope.loadMore = function (takeRows) { //Not using takeRows parameter now. Will use it later.

        for (var i = 0; i < $scope.takeRows; i++) {
            $scope.items.push({ id: counter });
            counter += 10;
        }
    };

    $scope.loadMore();
}
]);

现在我的问题是我在我的应用程序中尝试了相同的代码 我看到了一个奇怪的问题。每当我的滚动到达底部时,我的指令就会被正确触发。但是 if 条件满足了两次,它从指令中触发 loadMore() 函数两次。条件如下面的代码所示 -

elm.bind('scroll', function () {
            if (raw.scrollTop + raw.offsetHeight >= raw.scrollHeight) {
                // scope.$apply(attr.whenScrolled({ id: takeRows }));
                scope.loadMore(takeRows);
                scope.$apply();
            }
        });

我尝试了很多来找出原因,但没有运气。这可能是我做错了什么。有人可以帮我解决这个问题吗? 提前感谢任何帮助/建议。

【问题讨论】:

    标签: angularjs angularjs-directive


    【解决方案1】:

    这意味着你的元素已经绑定了两次scroll事件,你可以确保事件在绑定之前只通过unbind滚动事件绑定一次。

    代码

    ele.unbind('scroll');
    elm.bind('scroll', function() {
        if (raw.scrollTop + raw.offsetHeight >= raw.scrollHeight) {
            // scope.$apply(attr.whenScrolled({ id: takeRows }));
            scope.loadMore(takeRows);
            scope.$apply();
        }
    });
    

    更新

    除了此代码之外,如果已经有任何服务调用正在进行,您 scope.loadMore(takeRows) 不应调用该服务,这可以使用 Promise 概念来完成。以编程方式实现此逻辑将是一个好主意。

    【讨论】:

    • 你好 pankaj。感谢您的快速回复。我会尝试取消绑定滚动事件。
    • 嗨,Pankaj。我尝试在绑定之前取消绑定滚动事件。但它仍然会触发两次。
    • 我注意到的另一件事是,相同的代码在 Google Chrome 和 Mozilla 中运行良好。我只面临 IE (V 11) 的问题。
    • @saajshek 它每次都会发生或只发生一次
    • 每次滚动到底部时,指令中两次满足if条件。
    猜你喜欢
    • 2014-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-10
    相关资源
    最近更新 更多