【发布时间】:2013-05-03 08:23:36
【问题描述】:
我有一个使用 AngularJS 编写的网络应用程序:http://asmor.com/anr
此应用程序用于帮助为特定游戏构建套牌。
当您将卡片添加到牌组时,它们会添加到右上角的固定位置 div。该 div 具有动态设置的最大高度,因此它不会被浏览器窗口的底部或页面右下角的另一个固定 div 遮挡。
如果您达到最大高度,套牌中的卡牌列表会滚动。见下文:
现在的问题是,当您通过单击红色或绿色按钮滚动卡组时从卡组中添加或删除卡时,Angular 会重新绘制卡组列表并将滚动重置回顶部。
为方便起见,这是我用于牌组列表的代码:
<div id="deck" class="shown-{{ deck.notEmpty }} faction{{ deck.identity.faction }}">
<div class="deckStat cardTotal">
<strong class="valid-{{ deck.enoughCards }}">Cards:</strong> {{ deck.cardCount }} / {{ deck.minCards }}
</div>
<div class="deckStat agendaPointsTotal shown-{{ deck.isCorp }}">
<strong class="valid-{{ deck.enoughAgendaPoints }}">Agenda points:</strong> {{ deck.totalPoints }} / {{ deck.minPoints }}
</div>
<div class="deckStat influencePointsTotal">
<strong class="valid-{{ deck.withinInfluenceLimit }}">Influence points:</strong> {{ deck.influenceTotal }} / {{ deck.influenceAvailable }}
</div>
<div class="deckIdentity" ng-mouseover="setPreviewLink(deck.identity)">
<strong>Identity:</strong>
{{ deck.identity.name }}
</div>
<div id="deckScrollContainer" style="max-height: {{ getMaxDeckHeight() }}px">
<ul ng-repeat="(typeName, typeHash) in deck.cardsByType">
<li class="deckTypeHeader">
<strong>{{ typeName }}</strong>
<span class="quantity">
({{ typeHash.qty }})
</span>
</li>
<li ng-repeat="(cardName, qty) in typeHash.cards" class="card faction{{ getCardFaction(cardName) }}" ng-mouseover="setPreviewLink(cardName)">
<button class="btn btn-mini btn-success add qty{{qty}}" ng-click="addCard(cardName)"><i class="icon-plus"></i></button>
<button class="btn btn-mini btn-danger remove qty{{qty}}" ng-click="removeCard(cardName)"><i class="icon-minus"></i></button>
<span class="quantity">
{{ qty }}x
</span>
{{ cardName }}
<span class="influence">
{{ getInfluenceString(cardName, qty) }}
</span>
</li>
</ul>
</div>
</div>
我尝试过的一件事是在您添加或删除将抓住当前滚动位置的卡片时添加一个函数,然后再替换它。
$scope.addCard = function (c) {
$scope.setDeckScroll();
$scope.deck.add(c);
};
$scope.setDeckScroll = function () {
$scope.deckScrollPosition = document.getElementById("deckScrollContainer").scrollTop;
};
还有……
$scope.getCardFaction = function (card) {
$scope._persist();
card = getCardByName(card);
return card.faction;
};
$scope._persist = function () {
// Any weird stuff that needs to be done on redraw/refresh
if ($scope.deckScrollPosition) {
document.getElementById("deckScrollContainer").scrollTop = $scope.deckScrollPosition;
$scope.deckScrollPosition = null;
}
};
据我所知,Angular 在重绘页面时会多次重绘页面。我不知道最后一次重新绘制是什么时候,我不能每次都盲目地设置 scrollPosition 因为如果有人自己滚动到顶部,我将无法区分两者之间的区别以及是否因为重绘而滚动到顶部。
我考虑过的一个选项是使用 setTimeout 来清除 $scope.deckScrollPosition,这样
我能够通过使用 setTimeout 清除滚动位置变量来使其工作(这样每次重绘都可以访问该变量)
$scope._persist = function () {
// Any weird stuff that needs to be done on redraw/refresh
if ($scope.deckScrollPosition) {
document.getElementById("deckScrollContainer").scrollTop = $scope.deckScrollPosition;
setTimeout(function () {
$scope.deckScrollPosition = null;
}, 100);
}
};
...但这似乎真的很hacky。我希望可能有更好的方法。任何关于我怎么做的想法......
每次更改数据时只重绘一次 Angular(例如,也许我编写的代码很糟糕,迫使它重绘多次?)
在不使用 setTimeout 诡计的情况下以某种方式应对重绘?
【问题讨论】:
标签: javascript angularjs scroll