AngularJS中如何对ng-repeat的键值对按value排序?
解决AngularJS中对象键值对按Value排序并保留ID的问题
嘿,我懂你遇到的这个坑——AngularJS的orderBy过滤器对对象类型的数据确实不太友好,它本质上是为数组设计的。而且你用Underscore.js时丢失ID,大概率是没把ID和Value一起封装成对象保存,咱们一步步来解决:
问题根源
你当前的$scope.sports是一个键值对对象,而AngularJS的orderBy过滤器无法直接对对象的属性值进行排序(早期AngularJS版本中,对象的属性枚举顺序还依赖浏览器实现,稳定性很差)。直接用orderBy:'value'自然不会生效。
解决方案1:在控制器中将对象转为带ID的数组(最可靠)
把键值对对象转换成包含id和name(或value)的数组,这样既能用原生orderBy排序,也能完整保留ID信息。
用Underscore.js实现:
// 控制器内处理 $scope.sportsList = _.map($scope.sports, function(value, id) { return { id: parseInt(id), // 把字符串ID转为数字,避免后续可能的排序异常 name: value }; }); // 直接在数组上按name排序 $scope.sportsList = _.sortBy($scope.sportsList, 'name');
用原生JS实现(无需Underscore):
// 控制器内处理 $scope.sportsList = Object.entries($scope.sports) .map(([id, value]) => ({ id: Number(id), name: value })) .sort((a, b) => a.name.localeCompare(b.name)); // 按名称自然排序
视图层代码修改:
<ul> <li ng-repeat="sport in sportsList"> <a ng-href='/page/{{sport.id}}'>{{sport.name}}</a> </li> </ul>
解决方案2:自定义过滤器处理对象排序
如果你不想修改控制器里的数据结构,可以自定义一个过滤器,专门把对象转为可排序的数组:
注册自定义过滤器:
angular.module('yourAppName') .filter('orderObjectBy', function() { return function(items, field, reverse) { // 把对象转为包含ID和Value的数组 var filtered = []; angular.forEach(items, function(value, key) { filtered.push({ id: key, value: value }); }); // 按Value排序 filtered.sort(function(a, b) { return a.value.localeCompare(b.value); }); // 支持反向排序 if (reverse) { filtered.reverse(); } return filtered; }; });
视图层直接使用过滤器:
<ul> <li ng-repeat="sport in sports | orderObjectBy:'value'"> <a ng-href='/page/{{sport.id}}'>{{sport.value}}</a> </li> </ul>
为什么你之前用Underscore会丢失ID?
大概率是你直接使用了_.values($scope.sports)这类只提取值的方法,没有把ID作为属性一起封装到结果里。只要在转换时把ID和Value配对成对象,就能完美保留所有信息啦。
内容的提问来源于stack exchange,提问作者eudaimonia
相关产品推荐
相关产品推荐

