我正在使用 AngularJS 创建一个页面,其中包含显示名称、价格、区域等信息的产品列表。这显示得有点像 Accordion ,名称在标题中,额外信息在正文中。
由于可能会显示大量这些项目,因此我使用 dirPagination ( https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination ) 对这些项目进行分页。我目前的标记如下所示:
<div class="custom-list" dir-paginate="asset in assets | itemsPerPage: 10 track by $index">
<div class="custom-list-item" ng-class="{'tag-hover': isHoveredTag(asset)}">
<div class="custom-list-item-heading" ng-click="toggleShowAssetDetails(asset)">
<p class="col-lg-5">{{ asset.name }}</p>
<div class="col-lg-offset-2 col-lg-3 rating">
<rating value="asset.rating" />
</div>
<button ng-click="addAsset(asset)"><span class="glyphicon glyphicon-plus"></span></button>
<div class="clearfix"></div>
</div>
<div class="custom-list-item-content" style="display: none" animate="shouldShowAssetDetails(asset)">
...
</div>
</div>
</div>
正如您所看到的,我以一种非常标准的方式使用分页,只是循环遍历数组中的项目并每页显示 10 个项目。我还有一个名为 rating 的指令,它查看项目中名为 rating 的值。这是 1 - 5 之间的数字,用于在名称旁边显示星级评级系统。该指令如下所示:
var rating = function ($compile) {
return {
restrict: "E",
scope: {
value: "="
},
link: function (scope, element, attrs) {
scope.$watch(attrs.rating, function () {
for (var i = 1; i <= 5; i++) {
if (i <= scope.value) {
var starElement = angular.element("<span class=\"icon icon-crown\"></span>");
$compile(starElement)(scope);
element.append(starElement);
} else {
var emptyStarElement = angular.element("<span class=\"icon-empty icon-crown\"></span>");
$compile(emptyStarElement)(scope);
element.append(emptyStarElement);
}
}
})
}
}
}
这会查看该值并根据评级值插入图标(例如,如果评级为 2,则指令将插入两个图标-皇冠图标跨度和 3 个图标-空图标-皇冠图标跨度。
在我添加分页之前,它工作得非常好。但现在它仅适用于前 10 项。当您更改页面时,即使值不同,评级也不会改变,只是保留与上一页相同的图标。
我理解这是因为该指令在开始时设置了所有内容,并且当您更改页面时它不会运行,因为这些项目没有重新加载,它们只是再次显示和隐藏。但该指令正在操作 DOM,因此当页面更改时它不会更新。
问题是我不知道如何解决这个问题。我考虑过更改指令以查找分页当前页面,但随后我无法访问当前列表项。
如果您能在页面更改时获取更新图标的指令,我将不胜感激。
更新 以下是 Plunker 项目的链接,显示了我遇到的问题:http://plnkr.co/edit/VSQ20eWCwVpaCoS7SeQq?p=preview
这是我遇到问题的应用程序部分的一个非常精简的版本。尽管我保留了 CSS 类结构,但不包含样式。我还更改了图标以使用 Bootstrap 图标,只是为了简化 Plunker 项目。
但是功能是相同的。如果您从第 1 页翻到第 2 页,请注意尽管 Assets 评级值不同,但星星仍然保持不变。但是,如果您转到第 3 页并返回第 2 或 1 页,它们将会发生变化。发生这种情况的原因是因为第 3 页上的项目较少,因此当您返回到第 1 或第 2 页时,将再次调用剩余的项目来检索评级值。
最佳答案
您只需删除或替换 track by $index
。
通过 $index
进行跟踪将为您提供以下行为:
有一个最大长度为 10 的数组,表示要显示的项目。第一项的索引为 0。
您转到下一页,数组中的项目将被替换。
数组中的第一个项目仍将具有索引 0。由于您通过索引进行跟踪并且索引没有更改,因此 AngularJS 将不会重新创建表示该项目的 DOM 节点。由于未重新创建 DOM 节点,因此这次指令将不会执行,评级也不会更新。
如果从第 3 页转到第 2 页,该指令将对第 2 页上的最后 7 个元素执行,因为它们在第 3 页上不存在,因此这次它们被视为新元素。
如果您确实需要使用track by
,您应该使用与对象实际相关(且唯一)的属性,例如:
dir-paginate="asset in assets | itemsPerPage: 10 track by asset.name"
关于javascript - AngularJS:自定义指令不适用于 dirPagination,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28474483/