AngularJS如何根据条件在不同数组上使用ng-repeat且避免重复代码?
最佳实现方案:避免重复代码的三种优雅方式
这问题我太熟悉了!要解决这种「同一逻辑分支下复用大量重复代码」的问题,咱们有几个非常实用的方案,完全不用写两遍相同的模板代码,我给你逐个拆解:
方案一:用控制器函数动态返回数据源(最简单快捷)
这个方案是最轻量化的,不用额外模板或指令,只需要在控制器里加一个小函数,帮你根据ctrl.type返回对应的数组:
步骤1:在控制器里添加函数
// 假设这是你的控制器代码 angular.module('yourApp').controller('YourCtrl', function() { const ctrl = this; // 新增这个函数:根据类型返回对应的items数组 ctrl.getCategoryItems = function(category) { return ctrl.type === 'group' ? category.group_items : category.data.other_items; }; // 你的其他控制器逻辑... });
步骤2:在模板里统一调用
现在模板里只需要写一遍公共代码,直接用这个函数作为ng-repeat的数据源:
<div ng-repeat="category in ctrl.categories"> <!-- 这里是你不想重复的「...」公共代码 --> <h3>{{category.name}}</h3> <!-- 统一的item循环 --> <div ng-repeat="item in ctrl.getCategoryItems(category)"> <!-- 这里也是你不想重复的item渲染代码 --> <p>{{item.label}}</p> </div> </div>
优点:代码最简洁,零额外文件,适合逻辑简单的场景;注意:函数要尽量轻量,避免在里面做复杂计算,防止Angular的脏检查频繁触发影响性能。
方案二:提取公共模板,用ng-include复用(适合复杂模板)
如果你的「...」部分代码量很大,或者以后需要单独维护这部分模板,推荐把公共代码抽成独立模板,再用ng-include引入:
步骤1:定义公共模板
你可以直接在当前页面里用<script>标签定义模板,也可以单独存成HTML文件:
<!-- 放在当前页面的任意位置,比如body末尾 --> <script type="text/ng-template" id="category-item-template.html"> <!-- 这里是你的公共「...」代码 --> <h3>{{category.name}}</h3> <!-- 这里用$ctrl.items作为统一的数据源 --> <div ng-repeat="item in $ctrl.items"> <p>{{item.label}}</p> </div> </script>
步骤2:主模板里切换数据源并引入模板
用ng-switch或者ng-if判断类型,同时给公共模板传递对应的数组:
<div ng-repeat="category in ctrl.categories"> <div ng-switch on="ctrl.type"> <!-- 当type为group时,传递group_items --> <div ng-switch-when="group" ng-include="'category-item-template.html'" ng-init="$ctrl.items = category.group_items"></div> <!-- 其他情况传递other_items --> <div ng-switch-default ng-include="'category-item-template.html'" ng-init="$ctrl.items = category.data.other_items"></div> </div> </div>
优点:公共模板完全抽离,复用性强,适合复杂的UI结构;如果模板代码很多,单独存成文件会更方便维护。
方案三:封装自定义指令(适合组件化复用)
如果这个分类列表组件需要在多个页面或模块里复用,那自定义指令是最专业的方案,把逻辑和模板完全封装起来:
步骤1:定义指令
angular.module('yourApp').directive('categoryList', function() { return { scope: { // 接收外部传入的categories和type categories: '=', type: '=' }, controllerAs: '$ctrl', bindToController: true, templateUrl: 'category-list.html' // 指令的模板文件 }; });
步骤2:指令模板文件(category-list.html)
在模板里直接处理类型判断,不用重复代码:
<div ng-repeat="category in $ctrl.categories"> <!-- 公共代码部分 --> <h3>{{category.name}}</h3> <!-- 直接在ng-repeat里判断类型,返回对应数组 --> <div ng-repeat="item in ($ctrl.type === 'group' ? category.group_items : category.data.other_items)"> <p>{{item.label}}</p> </div> </div>
步骤3:在页面里使用指令
<!-- 直接传入你的数据和类型即可 --> <category-list categories="ctrl.categories" type="ctrl.type"></category-list>
优点:完全组件化,逻辑和模板封装在一起,可复用性最高,适合大型Angular项目的组件化开发。
方案选择建议
- 简单场景、代码量少:优先选方案一;
- 公共模板复杂、需要单独维护:选方案二;
- 需要跨页面/模块复用:选方案三。
内容的提问来源于stack exchange,提问作者ehacinom
相关产品推荐
相关产品推荐

