如何在没有 JQuery 的情况下正确实现无限滚动 AngularJS table?
How to properly implement an infinite scrolling AngularJS table without JQuery?
我有一个 AngularJS 项目(我不使用 JQuery),我需要向用户显示 table 并在用户滚动到项目末尾时加载更多内容这一页。我试图在不依赖外部库的情况下实现它,因为这是我要求的一部分。
我检查了几个例子,比如 this, this and this。
但到目前为止,none 个我检查过的示例帮助我实现了我预期的无限滚动。他们使用不同的方法来计算何时触发调用,其中一些值 return 对我来说是未定义的(即人们说 clientHeight 和 scrollHeight 具有不同的值,但对我来说它总是相同的,总高度包括滚动space).
我创建了如下指令:
usersModule.directive('whenScrollEnds', function($window) {
return {
restrict: "A",
link: function(scope, elm, attr) {
angular.element($window).bind('scroll', function() {
var hiddenContentHeight = elm[0].scrollHeight - angular.element($window)[0].innerHeight;
if ((hiddenContentHeight - angular.element($window)[0].scrollY) <= (10 )) {
angular.element($window)[0].requestAnimationFrame(function(){
scope.$apply(attr.whenScrollEnds);
})
}
});
}
};
});
这种作品,但有以下problems/doubts,我希望有人能给我解释一下:
- 触发太快了。我希望当我接近可滚动 space 的底部时触发加载,比如接近 90% 左右。
- scrollHeight 只能通过 elm[0] 访问,angular.element($window)[0] 没有 scrollHeight 属性 所以它 return 未定义,并且 elm[0] 没有 scrollY 值。
- 我得到的scrollY值是滚动条从顶部移动的距离减去滚动条长度,但我觉得那个值是错误的。
- 通过angular.element($window).bind 绑定滚动事件是正确的决定吗?
如何实现正确的无限滚动table?我使用的变量是否正确?请提供仅使用 Javascript 和 AngularJS 的答案,JQuery 或库解决方案对我没有帮助。
在检查了几个示例并尝试避免使用 JQuery 作为解决方案的一部分之后,我找到了一种方法来完成这项工作。
首先我的指令将在滚动结束时处理:
usersModule.directive('whenScrollEnds', function($window) {
return {
restrict: "A",
link: function(scope, elm, attr) {
var raw = elm[0];
raw.addEventListener('scroll', function() {
if ((raw.scrollTop + raw.clientHeight) >= (raw.scrollHeight )) {
scope.$apply(attr.whenScrollEnds);
}
});
}
};
});
我的视图在 div
中有 table,如下所示:
<div id="usersScrollable" when-scroll-ends="uc.loadMoreUsers()">
<table id="tableUsers" class="table" ng-show="uc.users.length" >
<thead>
<tr>
<th>Email</th>
<th>Nombre Completo</th>
<th>Estado</th>
<th>Acción</th>
</tr>
</thead>
<tbody >
<tr ng-repeat="u in uc.users">
<td>{{u.email}}</td>
<td>{{u.fullName}}</td>
<td>{{uc.getStateString(u.active)}}</td>
<td><button type="button" class="btn btn-primary" ng-click="uc.edit(u)">Editar</button></td>
</tr>
</tbody>
</table>
</div>
确保包含 table 的 div
是滚动结束时收听的那个。这个 div
必须有一个设置的高度,如果没有那么 clientHeight
属性 将与 scrollHeight
相同(不知道如果没有高度会发生什么明确定义,例如设置顶部或底部属性而不是设置高度)。
在我的控制器中,loadMoreUsers()
负责增加页面(如果有更多用户,我接到的每个电话都有用户总数,所以我可以在发出另一个请求之前知道我有多少用户左),它还调用向 Web 服务发出请求的函数。
Uriel Arvizu提供的解决方案的问题是,如果raw
元素是空的,因为它在页面加载时等待Http Request,下面的所有raw.scrollTop
,raw.clientHeight)
和 raw.scrollHeight
将有错误的尺寸,卷轴不再工作。
我会建议其他解决方案,基本上将滚动事件添加到 $window
而无需缓存它,因此在收到 Http 响应时它的大小总是正确的。
(function () {
'use strict';
angular.module('ra.infinite-scroll', []).directive('infiniteScroll', function ($window) {
return {
restrict: 'A',
scope: {
infiniteScrollCallbackFn: '&'
},
link: function (scope, elem, attrs) {
var percentage = (attrs.infiniteScrollPercentage !== undefined ? (attrs.infiniteScrollPercentage / 100) : '.9');
var $element = elem[0];
angular.element($window).on('scroll', function () {
if ((this.scrollY + this.innerHeight - $element.offsetTop) >= ($element.scrollHeight * percentage)) {
scope.$apply(scope.infiniteScrollCallbackFn);
}
});
}
};
});
})();
此外,对于此模块,您可以在 HTML 中传递 2 个参数:回调函数和特定元素(应用模块的位置)到达回调函数时的百分比调用,即重复 Http 请求(默认为该元素的 90%)。
<div infinite-scroll infinite-scroll-callback-fn="callBackFunction()" infinite-scroll-percentage="80">
// Here you may include the infinite repeating template
</div>
使用 Ferie 的示例代码,但我不得不使用 mousewheel
事件而不是 scroll
,并且不得不使用 elem.scrollTop()
而不是 elem.scrollY
app.directive('infiniteScroll', function ($window) {
return {
restrict: 'A',
scope: {
infiniteScrollCallbackFn: '&'
},
link: function (scope, elem, attrs) {
var percentage = (attrs.infiniteScrollPercentage !== undefined ? (attrs.infiniteScrollPercentage / 100) : '.9');
var $element = elem[0];
angular.element($window).on('mousewheel', function () {
if ((elem.scrollTop() + this.innerHeight - $element.offsetTop) >= ($element.scrollHeight * percentage)) {
scope.$apply(scope.infiniteScrollCallbackFn);
}
});
}
};
});
当在 Angular table 中与 <tr>
上的 ng-repeat 一起使用时,我必须将该指令添加到此 [=18] 的父 tbody
中=] 以便捕获包含滚动状态的正确元素。
<tbody infinite-scroll infinite-scroll-callback-fn="callBackFunction()" infinite-scroll-percentage="80">
我有一个 AngularJS 项目(我不使用 JQuery),我需要向用户显示 table 并在用户滚动到项目末尾时加载更多内容这一页。我试图在不依赖外部库的情况下实现它,因为这是我要求的一部分。
我检查了几个例子,比如 this, this and this。
但到目前为止,none 个我检查过的示例帮助我实现了我预期的无限滚动。他们使用不同的方法来计算何时触发调用,其中一些值 return 对我来说是未定义的(即人们说 clientHeight 和 scrollHeight 具有不同的值,但对我来说它总是相同的,总高度包括滚动space).
我创建了如下指令:
usersModule.directive('whenScrollEnds', function($window) {
return {
restrict: "A",
link: function(scope, elm, attr) {
angular.element($window).bind('scroll', function() {
var hiddenContentHeight = elm[0].scrollHeight - angular.element($window)[0].innerHeight;
if ((hiddenContentHeight - angular.element($window)[0].scrollY) <= (10 )) {
angular.element($window)[0].requestAnimationFrame(function(){
scope.$apply(attr.whenScrollEnds);
})
}
});
}
};
});
这种作品,但有以下problems/doubts,我希望有人能给我解释一下:
- 触发太快了。我希望当我接近可滚动 space 的底部时触发加载,比如接近 90% 左右。
- scrollHeight 只能通过 elm[0] 访问,angular.element($window)[0] 没有 scrollHeight 属性 所以它 return 未定义,并且 elm[0] 没有 scrollY 值。
- 我得到的scrollY值是滚动条从顶部移动的距离减去滚动条长度,但我觉得那个值是错误的。
- 通过angular.element($window).bind 绑定滚动事件是正确的决定吗?
如何实现正确的无限滚动table?我使用的变量是否正确?请提供仅使用 Javascript 和 AngularJS 的答案,JQuery 或库解决方案对我没有帮助。
在检查了几个示例并尝试避免使用 JQuery 作为解决方案的一部分之后,我找到了一种方法来完成这项工作。
首先我的指令将在滚动结束时处理:
usersModule.directive('whenScrollEnds', function($window) {
return {
restrict: "A",
link: function(scope, elm, attr) {
var raw = elm[0];
raw.addEventListener('scroll', function() {
if ((raw.scrollTop + raw.clientHeight) >= (raw.scrollHeight )) {
scope.$apply(attr.whenScrollEnds);
}
});
}
};
});
我的视图在 div
中有 table,如下所示:
<div id="usersScrollable" when-scroll-ends="uc.loadMoreUsers()">
<table id="tableUsers" class="table" ng-show="uc.users.length" >
<thead>
<tr>
<th>Email</th>
<th>Nombre Completo</th>
<th>Estado</th>
<th>Acción</th>
</tr>
</thead>
<tbody >
<tr ng-repeat="u in uc.users">
<td>{{u.email}}</td>
<td>{{u.fullName}}</td>
<td>{{uc.getStateString(u.active)}}</td>
<td><button type="button" class="btn btn-primary" ng-click="uc.edit(u)">Editar</button></td>
</tr>
</tbody>
</table>
</div>
确保包含 table 的 div
是滚动结束时收听的那个。这个 div
必须有一个设置的高度,如果没有那么 clientHeight
属性 将与 scrollHeight
相同(不知道如果没有高度会发生什么明确定义,例如设置顶部或底部属性而不是设置高度)。
在我的控制器中,loadMoreUsers()
负责增加页面(如果有更多用户,我接到的每个电话都有用户总数,所以我可以在发出另一个请求之前知道我有多少用户左),它还调用向 Web 服务发出请求的函数。
Uriel Arvizu提供的解决方案的问题是,如果raw
元素是空的,因为它在页面加载时等待Http Request,下面的所有raw.scrollTop
,raw.clientHeight)
和 raw.scrollHeight
将有错误的尺寸,卷轴不再工作。
我会建议其他解决方案,基本上将滚动事件添加到 $window
而无需缓存它,因此在收到 Http 响应时它的大小总是正确的。
(function () {
'use strict';
angular.module('ra.infinite-scroll', []).directive('infiniteScroll', function ($window) {
return {
restrict: 'A',
scope: {
infiniteScrollCallbackFn: '&'
},
link: function (scope, elem, attrs) {
var percentage = (attrs.infiniteScrollPercentage !== undefined ? (attrs.infiniteScrollPercentage / 100) : '.9');
var $element = elem[0];
angular.element($window).on('scroll', function () {
if ((this.scrollY + this.innerHeight - $element.offsetTop) >= ($element.scrollHeight * percentage)) {
scope.$apply(scope.infiniteScrollCallbackFn);
}
});
}
};
});
})();
此外,对于此模块,您可以在 HTML 中传递 2 个参数:回调函数和特定元素(应用模块的位置)到达回调函数时的百分比调用,即重复 Http 请求(默认为该元素的 90%)。
<div infinite-scroll infinite-scroll-callback-fn="callBackFunction()" infinite-scroll-percentage="80">
// Here you may include the infinite repeating template
</div>
使用 Ferie 的示例代码,但我不得不使用 mousewheel
事件而不是 scroll
,并且不得不使用 elem.scrollTop()
而不是 elem.scrollY
app.directive('infiniteScroll', function ($window) {
return {
restrict: 'A',
scope: {
infiniteScrollCallbackFn: '&'
},
link: function (scope, elem, attrs) {
var percentage = (attrs.infiniteScrollPercentage !== undefined ? (attrs.infiniteScrollPercentage / 100) : '.9');
var $element = elem[0];
angular.element($window).on('mousewheel', function () {
if ((elem.scrollTop() + this.innerHeight - $element.offsetTop) >= ($element.scrollHeight * percentage)) {
scope.$apply(scope.infiniteScrollCallbackFn);
}
});
}
};
});
当在 Angular table 中与 <tr>
上的 ng-repeat 一起使用时,我必须将该指令添加到此 [=18] 的父 tbody
中=] 以便捕获包含滚动状态的正确元素。
<tbody infinite-scroll infinite-scroll-callback-fn="callBackFunction()" infinite-scroll-percentage="80">