Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 刷新后在AngularJS中保持滚动位置_Javascript_Angularjs_Scroll - Fatal编程技术网

Javascript 刷新后在AngularJS中保持滚动位置

Javascript 刷新后在AngularJS中保持滚动位置,javascript,angularjs,scroll,Javascript,Angularjs,Scroll,我有一个用AngularJS编写的web应用程序: 此应用程序用于帮助为特定游戏构建平台 当你向牌组中添加卡片时,它们会被添加到右上角的固定位置的div中。该div具有动态设置的最大高度,因此不会被浏览器窗口底部或页面右下角的另一个固定div遮挡 如果达到最大高度,牌组中的牌列表将滚动。见下文: 现在的问题是,当您通过单击红色或绿色按钮滚动卡片时,从卡片组中添加或删除卡片时,Angular会重新绘制卡片组列表,并将滚动重置回顶部 为了方便起见,下面是我在甲板列表中使用的代码: <div

我有一个用AngularJS编写的web应用程序:

此应用程序用于帮助为特定游戏构建平台

当你向牌组中添加卡片时,它们会被添加到右上角的固定位置的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.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清除scroll position变量使其工作(这样每个重画都可以访问该变量)

…但这似乎真的很难。我希望有更好的办法。有没有关于我可以

  • 每次数据更改只重新绘制一次角度图(例如,可能我的代码编写得不好,这会迫使它重新绘制多次?)

  • 在不诉诸诡计的情况下,以某种方式应对重画

  • 在这里找到了答案:

    例如plunkr,这里有一点定制:

    基本上,您可以设置location.hash并滚动到它。希望它能为您工作,因为您的设置有点复杂


    e:刚才注意到它实际上将视口聚焦在最后一个项目上,这实际上是不需要的。

    有几件事情应该对您有所帮助。如果
    deck.cardsByType
    中的项目有一个ID或某个唯一字段,您可以告诉AngularJS跟踪项目,并且只重新绘制具有新ID的项目,其他项目将得到更新,这将停止重新绘制整个列表:

    <li ng-repeat="(cardName, qty) in typeHash.cards track by id">
    
    然后在控制器中添加带有要调用的函数的指令

    <li 
      ng-repeat="(cardName, qty) in typeHash.cards track by id"
      repeat-load="loadedElement()"
    >
    

    我认为这不适合我的情况。首先,我并没有试图滚动到某个特定的元素,我只是试图防止div在被重画时跳转。其次,我不清楚这是否适用于滚动div中的某些内容;它似乎是用来滚动文档的。第三,这似乎也不能帮助我解决多重重画的问题。你看过plunker吗?它可以完全满足您的需求,尽管它可能不是精确的技术解决方案。我更改了CSS以镜像页面上的内容。如果视图被重画得太多或太少,这并不是特定于您的代码,而是angular的摘要周期。如果你认为是这样,你应该提出一个新问题。
    <li ng-repeat="(cardName, qty) in typeHash.cards track by id">
    
    app.directive( 'repeatLoad', function(){
        return {
            link: function( scope, element, attrs ) {
                scope.$eval( attrs['repeatLoad'] );
            }
        }
    }); 
    
    <li 
      ng-repeat="(cardName, qty) in typeHash.cards track by id"
      repeat-load="loadedElement()"
    >
    
    $scope.cnt_cards = 0;
    $scope.loaded_cards = 0;
    
    $scope.loadedElement = function() {
      $scope.loaded_cards++;
    
      if( $scope.cnt_cards == $scope.loaded_cards ) {
        console.log('All cards loaded');
      }
    }