我尝试从解决方案到这个工作
How to retain scroll position of ng-repeat in AngularJS?
在删除ng-repeat中的顶部项目时保持滚动位置,但无法找出执行此操作的代码.
另外,请注意,列表应按照与项目数组相同的顺序打印,而不是像示例那样反向打印.
angular.module("Demo",[]) .controller("DemoCtrl",function($scope) { $scope.items = []; for (var i = 0; i < 10; i++) { $scope.items[i] = { id: i,name: 'item ' + i }; } $scope.addNewItem = function() { $scope.items = $scope.items.concat({ id: $scope.items.length,name: "item " + $scope.items.length }); }; }) .directive("keepScroll",function(){ return { controller : function($scope){ var element = 0; this.setElement = function(el){ element = el; } this.addItem = function(item){ console.log("Adding item",item,item.clientHeight); element.scrollTop = (element.scrollTop+item.clientHeight+1); //1px for margin }; },link : function(scope,el,attr,ctrl) { ctrl.setElement(el[0]); } }; }) .directive("scrollItem",function(){ return{ require : "^keepScroll",att,scrCtrl){ scrCtrl.addItem(el[0]); } } })
我尝试做的是改变
element.scrollTop = (element.scrollTop + item.clientHeight+1)
至
element.scrollTop = (element.scrollTop - item.clientHeight+1)
并按’id’而不是’-id’按顺序打印
我认为最初的解决方案有点像hacky ……但这是一个以它为基础的工作编辑.
原文链接:https://www.f2er.com/angularjs/141106.html问题是解决方案取决于添加到ng-repeat的项目.如果查看scrollItem指令,它只会导致keepScroll指令在链接器执行时重新调整scrollTop.这仅在项目添加而不是删除时发生.
而编辑则侦听范围.$on(‘$destroy’)事件.但是,此时的问题是该元素不再具有clientHeight,因为它已从DOM中删除.因此解决方案是在创建时保存其高度,然后告诉keepScroll删除元素的高度是多少.
注意:如果滚动条一直到底部,这似乎会导致滚动跳转,因此您需要将该情况视为异常.
工作JSBin:http://jsbin.com/geyapugezu/1/edit?html,output
以供参考:
HTML
<!DOCTYPE html> <html> <head> <script src="//code.angularjs.org/1.3.0-beta.7/angular.js"></script> <Meta charset="utf-8"> <title>JS Bin</title> </head> <body ng-app="Demo" ng-controller="DemoCtrl"> <div class="wrapper" keep-scroll> <div class="item" scroll-item ng-repeat="item in items | orderBy: 'id'"> {{ item.name }} </div> </div> <button ng-click="removeItem()"> Remove item </button> </body> </html>
CSS
.wrapper { width: 200px; height: 300px; border: 1px solid black; overflow: auto; } .item { background-color: #ccc; height: 100px; margin-bottom: 1px; }
JS
angular.module("Demo",[]) .controller("DemoCtrl",function($scope) { $scope.items = []; for (var i = 0; i < 10; i++) { $scope.items[i] = { id: i,name: 'item ' + i }; } $scope.removeItem = function() { $scope.items = $scope.items.slice(1); }; }) .directive("keepScroll",function(){ return { controller : function($scope){ var element = 0; this.setElement = function(el){ element = el; }; this.itemRemoved = function(height){ element.scrollTop = (element.scrollTop - height - 1); //1px for margin console.log("Item removed",element.scrollTop); }; },ctrl) { ctrl.setElement(el[0]); } }; }) .directive("scrollItem",function(){ return { require : "^keepScroll",scrCtrl){ var height = el[0].clientHeight; scope.$on('$destroy',function() { scrCtrl.itemRemoved(height); }); } }; });
编辑
或者,这样做.不需要scrollItem,而是我们观察ng-repeat项目的更改并相应地重新调整scrollTop.
JSBin:http://jsbin.com/dibeqivubi/edit?html,output
JS
angular.module("Demo",['$scope',name: 'item ' + i }; } $scope.removeItem = function() { $scope.items = $scope.items.slice(1); }; }]) .directive("keepScroll",function() { return { link : function(scope,ctrl) { var scrollHeight; scope.$watchCollection('items',function(n,o) { // Instantiate scrollHeight when the list is // done loading. scrollHeight = scrollHeight || el[0].scrollHeight; // Adjust scrollTop if scrollHeight has changed (items // have been removed) el[0].scrollTop = el[0].scrollTop - (scrollHeight - el[0].scrollHeight); // Remember current scrollHeight for next change. scrollHeight = el[0].scrollHeight; }); } }; });
HTML
<!DOCTYPE html> <html> <head> <script src="//code.angularjs.org/1.3.0-beta.7/angular.js"></script> <Meta charset="utf-8"> <title>JS Bin</title> </head> <body ng-app="Demo" ng-controller="DemoCtrl"> <div class="wrapper" keep-scroll> <div class="item" ng-repeat="item in items | orderBy: 'id'"> {{ item.name }} </div> </div> <button ng-click="removeItem()"> Remove item </button> </body> </html>