[TOC]
# ng-repeat指令
## 簡介
使用指令復制元素在構建模板內容的過程中,有時需要反復將不同的數據加載到一個元素中,例如,通過`<li>`元素綁定一個數組的各成員。此時,可以使用“ng-repeat”指令,它的功能是根據綁定數組成員的數量,復制頁面中被綁定的`<li>`元素,并在復制過程中添加元素相應的屬性和方法,通過這種方式,實現數組數據與元素綁定的過程。在使用“ng-repeat”指令復制元素的過程中,還提供了幾個非常實用的專有變量,可以通過這些變量來處理顯示數據時的各種狀態。
* $first,該變量表示記錄是否是首條,如果是則返回true,否則返回false。
* $last,該變量表示記錄是否是尾條,如果是則返回true,否則返回false。
* $middle,該變量表示記錄是否是中間條,如果是則返回true,否則返回false。
* $index,該變量表示記錄的索引號,其對應的值從0開始。
* $even,該變量表示記錄是否是奇數條,如果是則返回true,否則返回false。
* $odd,該變量表示記錄是否是偶數條,如果是則返回true,否則返回false。
## 基本使用
~~~html
<ul>
<!--data為$scope中的數組-->
<!--in為關鍵字-->
<!--item為一個變量名,代表data里面的每一個元素-->
<li ng-repeat="item in data">
{{item.name}}
{{item.sex}}
{{item.age}}
{{item.score}}
</li>
</ul>
~~~
## 使用ng-repeat需要注意的問題
在Angular中,ng-repeat是一個非常重要的內部指令,它的功能是在遍歷數組過程中生成DOM元素,實現在頁面中展示列表數據中的功能,功能強大、使用簡單,但如果使用不當也容易出現一些問題,具體表現如下。
* 在使用過程中,如果有過濾器時,調用$index并不能準確定位到對應的記錄。
* 在調用ng-repeat指令重新請求數據,并不是在原來DOM元素中更新數據,而是再次新建DOM元素。
* 在通過ng-repeat指令生成的子元素中,如果通過父的scope對象更新數據時,不能直接更新遍歷的數組源,而必須逐個更新。
## 使用ng-repeat處理辦法
### 有過濾器的情況下使用ng-repeat
### 首先數據會都自帶不重復的id
### 在界面顯示的情況下,也會使用賦值表達式【item in localData=(data | filter:myfilter) 】
#### index.js
~~~js
//創建控制器
angular.module('myapp').controller('my_c', ['$filter', '$scope', function ($filter, $scope) {
// 數據
// 一般情況下,我們的數據都會帶有獨立的ID
$scope.data = [
{
id: 1,
name: 'hzj',
sex: '男',
age: 18,
score: 100
},
{
id: 2,
name: 'hzj',
sex: '男',
age: 28,
score: 100
},
{
id: 3,
name: 'hzj',
sex: '男',
age: 26,
score: 100
},
{
id: 4,
name: 'hzj',
sex: '男',
age: 30,
score: 100
},
{
id: 5,
name: 'hzj',
sex: '男',
age: 19,
score: 100
},
{
id: 6,
name: 'hzj',
sex: '男',
age: 22,
score: 100
},
{
id: 7,
name: 'hzj',
sex: '男',
age: 18,
score: 100
},
{
id: 8,
name: 'hzj',
sex: '男',
age: 21,
score: 100
},
{
id: 9,
name: 'hzj',
sex: '男',
age: 18,
score: 100
}
];
//自定義一個filter過濾器的過濾規則
$scope.myfilter = function (item) {
return item.age > 25;
};
// 刪除元素
// item參數為view傳遞過來的數據里面的某一項
$scope.removeItem = function (item) {
//使用angular.forEach方法查詢到數組中對應的下
//arrayItem為$scope.data里面的每一項
// index為arrayItem項在$scope.data中的下標
angular.forEach($scope.data, function (arrayItem, index) {
if (item.id === arrayItem.id) {
//找到元素對應的下標,然后刪除元素
$scope.data.splice(index, 1);
return;
}
});
};
}]);
~~~
#### index.html
~~~html
<!DOCTYPE html>
<!--加載模塊-->
<html lang="en" ng-app="myapp">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--加載樣式-->
<link rel="stylesheet" href="css/index.css">
<!--加載Angular類庫-->
<script src="bower_components/angular/angular.min.js"></script>
<!--加載模塊創建文件-->
<script src="js/app.js"></script>
<!--加載控制器創建文件-->
<script src="js/index.js"></script>
</head>
<body>
<!--加載控制器-->
<div ng-controller="my_c">
<!--帶過濾的數據-->
<table>
<thead>
<tr>
<td>行標</td>
<td>id</td>
<td>姓名</td>
<td>性別</td>
<td>年齡</td>
<td>分數</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<!--這里使用了過濾好的數據,原數據為data-->
<!--localData=( data |filter:myfilter)-->
<tr ng-repeat="item in localData =( data |filter:myfilter) ">
<td>{{$index}}</td>
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.sex}}</td>
<td>{{item.age}}</td>
<td>{{item.score}}</td>
<td>
<button ng-click="removeItem(item)">刪除</button>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="7">總人數為:{{localData.length}}</td>
</tr>
</tfoot>
</table>
<hr>
<!--原始數據-->
<table>
<thead>
<tr>
<td>行標</td>
<td>id</td>
<td>姓名</td>
<td>性別</td>
<td>年齡</td>
<td>分數</td>
</tr>
</thead>
<tbody>
<!--這里使用的是原數據-->
<tr ng-repeat="item in data">
<td>{{$index}}</td>
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.sex}}</td>
<td>{{item.age}}</td>
<td>{{item.score}}</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="6">總人數為:{{data.length}}</td>
</tr>
</tfoot>
</table>
</div>
</body>
</html>
~~~
#### 結果

#### 點擊刪除ID為3的元素之后

### 使用track by排序數據中的唯一id屬性
在使用ng-repeat指令顯示列表數據時,如果需要更新數據,那么頁面中原有的DOM元素在更新過程中并不會被重用,而是會被刪除,再重新生成與上次結構一樣的元素。反復生成DOM元素對頁面的加載來說,并不是一件好事,它不僅會延遲數據加載的速度,而且非常浪費頁面資源。為了解決這種現象,我們在使用ng-repeat指令更新數據時,需要使用track by對數據源進行排序,排序的字段為不可重復的id。放心每個數據庫里面的數據都會有id屬性
~~~html
<tr ng-repeat="item in localData =( data |filter:myfilter | orderBy:'-age' ) track by item.id">
<td>{{$index}}</td>
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.sex}}</td>
<td>{{item.age}}</td>
<td>{{item.score}}</td>
<td>
<button ng-click="removeItem(item)">刪除</button>
</td>
</tr>
~~~
~~~html
<tr ng-repeat="item in data track by item.id">
<td>{{$index}}</td>
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.sex}}</td>
<td>{{item.age}}</td>
<td>{{item.score}}</td>
</tr>
~~~
### ng-repeat結束事件【這里僅僅是參考,到了中級部分會出現自定義指令】
Angular并沒有ng-repeat結束事件監聽,我們必須自己自定義一個指令來完成
~~~js
//自定義指令repeatFinish
angular.module('myapp').directive('hzjEndRepeat', ['$timeout', function ($timeout) {
return {
restrict: 'A',
link: function (scope, element, attr) {
//scope為repeat出來的每個dom的作用域
//element為repeat當前的元素
//attr為屬性
if (scope.$last === true) {
//延遲一些執行
$timeout(function () {
//像父親發送事件
$scope.$emit('hzjEndRepeat');
});
}
}
};
}]);
~~~
~~~html
<div class="filter_row clearfix" ng-repeat="item in filterType" hzj-end-repeat>
</div>
~~~
- Angular簡介
- angular1資料網站
- Angular初級部分
- 打破傳統的前端
- Angular基本組成部分
- Angular環境搭建
- Angular項目測試
- Angular基礎概念
- Angular模塊
- Angular控制器
- Angular指令
- Angular表達式
- Angular視圖
- Angular基礎實戰
- Angular模塊創建和使用
- Angular控制器和模型創建
- scope對象
- 控制器中調度window對象和document對象
- Angular表達式調度過濾器
- Angular中的ng模塊全局方法
- Angular模板應用
- 使用指令復制元素
- 使用指令隱藏顯示元素
- Angular指令ng-if
- ng-src和ng-href
- Angular處理樣式
- Angular作用域事件傳遞
- 表單中的元素
- Angular初學者常見的坑
- 再論雙向綁定
- Angular中級部分
- Angular路由機制
- ui-router管理狀態
- ui-router狀態嵌套和視圖嵌套
- ui-router多個命名的視圖
- ui-router路由控制
- 自定義指令
- 自定義過濾器
- Angular項目目錄結構
- Angular服務
- Angular高級部分
- Angular依賴注入
- README