带条件的ng-repeat:如何遍历结构不一的JSON中prizes属性?
解决AngularJS中带条件遍历两种结构
prizes的问题 嘿,这个场景我之前开发时也碰到过!AngularJS的ng-repeat对数据结构的一致性要求比较高,不过我们可以通过预处理数据或者模板内条件判断两种方式来搞定两种不同结构的prizes属性,下面分常见场景给你具体方案:
场景1:prizes是数组 或 单个对象
比如你的JSON可能是这两种形式:
// 形式1:数组 { "prizes": [ {"name": "一等奖", "amount": 1000}, {"name": "二等奖", "amount": 500} ] } // 形式2:单个对象 { "prizes": {"name": "参与奖", "amount": 100} }
方法1:控制器预处理(推荐,模板更简洁)
在拿到数据后,先在控制器里把prizes统一转成数组格式,这样模板里就不用写复杂判断了:
// 假设你的数据存在$scope.data中 if (angular.isObject($scope.data.prizes) && !angular.isArray($scope.data.prizes)) { // 把单个对象包装成数组 $scope.data.prizes = [$scope.data.prizes]; }
之后模板直接正常使用ng-repeat:
<div ng-repeat="prize in data.prizes"> 奖项:{{prize.name}},金额:{{prize.amount}}元 </div>
方法2:模板内直接判断(适合快速调试场景)
如果不想修改控制器数据,也可以在模板里通过ng-if配合AngularJS的类型判断方法来处理:
<!-- 遍历数组形式的prizes --> <div ng-repeat="prize in data.prizes" ng-if="angular.isArray(data.prizes)"> 奖项:{{prize.name}},金额:{{prize.amount}}元 </div> <!-- 渲染单个对象形式的prizes --> <div ng-if="angular.isObject(data.prizes) && !angular.isArray(data.prizes)"> 奖项:{{data.prizes.name}},金额:{{data.prizes.amount}}元 </div>
⚠️ 注意:如果你的模板里访问不到angular.isArray这类方法,需要在控制器里把它们挂载到$scope上:
$scope.isArray = angular.isArray; $scope.isObject = angular.isObject;
然后模板里改成ng-if="isArray(data.prizes)"即可。
场景2:prizes是数组 或 键值对对象
如果你的prizes可能是数组,也可能是类似{key: value}的键值对集合:
// 形式1:数组 { "prizes": [{"id": 1, "name": "一等奖"}, {"id": 2, "name": "二等奖"}] } // 形式2:键值对对象 { "prizes": { "first": {"name": "一等奖"}, "second": {"name": "二等奖"} } }
方法1:控制器预处理统一结构
把键值对对象转成数组,方便ng-repeat遍历:
if (angular.isObject($scope.data.prizes) && !angular.isArray($scope.data.prizes)) { // 现代浏览器可用Object.values,老版本AngularJS可以用angular.forEach手动遍历 $scope.data.prizes = Object.values($scope.data.prizes); // 兼容老版本的写法: // let prizeArr = []; // angular.forEach($scope.data.prizes, function(prize) { // prizeArr.push(prize); // }); // $scope.data.prizes = prizeArr; }
模板依旧直接使用ng-repeat即可。
方法2:模板内分别遍历数组和对象
如果要保留原结构的键信息,可以在模板里分别处理:
<!-- 遍历数组 --> <div ng-repeat="prize in data.prizes" ng-if="isArray(data.prizes)"> {{prize.name}} </div> <!-- 遍历键值对对象,同时获取键名 --> <div ng-repeat="(prizeKey, prize) in data.prizes" ng-if="isObject(data.prizes) && !isArray(data.prizes)"> {{prizeKey}}:{{prize.name}} </div>
通用小技巧
如果两种结构差异更大(比如一种prizes里嵌套了items数组,另一种直接是数据),可以通过判断特定属性来区分:
<div ng-repeat="prize in data.prizes.items" ng-if="data.prizes.items"> <!-- 处理嵌套items的情况 --> </div> <div ng-repeat="prize in data.prizes" ng-if="!data.prizes.items"> <!-- 处理直接是数组的情况 --> </div>
总的来说,优先在控制器里预处理数据,这样模板逻辑更清晰,也更符合AngularJS的MVC思想~
内容的提问来源于stack exchange,提问作者Satyam Raj
相关产品推荐
相关产品推荐

