angularjs中使用ng-repeat的注意点

1、ng-repeat的数据不能出现重复项问题

通常情况下,ng-repeat的数据是不可以重复的,否则就会报错。原因是angular需要一个唯一值可以与生成的dom绑定,以便追踪.

解决方案:
<div ng-repeat="(key,value) in datas track by key"></div>

2、ng-repeat的性能问题

AngularJs 的 ng-repeat 让我们非常方便的遍历数组/对象来生成 Dom 元素,然后在使用过程中也需要注意性能问题。
原理:在项目中我们使用 ng-repeat 加载完一个列表后,如果再次请求数据,当 ng-repeat 的数组被替换时, 它默认并不会重新利用已有的 Dom 元素,而是直接将其全部删除并重新生成新的数组 Dom 元素。而频繁的操作dom显然是很不友好的。为什么 ng-repeat 不能利用已有的 dom 元素去更新数据呢?因为你没有把数组元素的标识属性告诉它,那么两次替换的时候它就没办法追踪了。我们可以看到 ng-repeat 往数组里每个元素加了一个 $$hashKey 的属性:

这里写图片描述

这个 key 是由 Angular 内部的 nextUid() 方法生成,类似数据库自增,但是是使用字符串。

现在我们明白了,因为每次替换数组都会导致 ng-repeat 为每个元素生成一个新 key, 所以根本没办法重用已有的 Dom 元素,那么我们可以使用下边的语法来避免这个问题:

<div ng-controller="Test">
    <button ng-click="request()">请求新数据</button>
    // 使用 track by 标识
    <div ng-repeat="user in users track by user.id">
        {{user.name}}
    </div>
</div>

这样 ng-repeat 就用将其缓存起来啦,当然可能你的数组元素没有一个标识属性,如果元素数量不多那么可以接受,不然还是建议你手动为其生成一个标识属性,类似于id。

3、ng-options遇到的问题

ng-options的使用原理和ng-repeat 是一致的,都可以很方便的遍历数组/对象。先来看一组代码:

$scope.selectDatas = [
            {
                id: "1",
                name: "apple"
            }, {
                id: "2",
                name: "origin"
            }, {
                id: "3",
                name: "bananer"
            },{
                id:"4",
                name:"pear"
            }];
html中展示:

<select ng-change="editChangeSelectDatas()"  ng-options="obj.name for obj in selectDatas" ></select>

这样就可以将下拉列表完美的展示出来了。当我们想下拉列表默认选中一个时,代码如下:

$scope.selectDataSelected = {name:"pear",id:"4"};
<select ng-change="editChangeSelectDatas()"  ng-options="obj.name for obj in selectDatas" ng-model="selectDataSelected"></select>

此时,默认选中pear,非常完美!然而当我在去变换选择其他项时,会发现下拉列表始终展示的是我默认设置为显示的那一项,what should i do?
原因:ng-repeat指令为集合中的每项都实例化一个模块。每个模块都有自己的scope,也就是说ng-model绑定的selectDataSelected的作用域已经发生变化,你在通过ng-repeat去设置 scope.selectDataSelected= scope.selectDatas[i],是无效的。因为每一个$scope.selectDataSelected都有自己的作用域。
解决方案:

$scope.obj = {selectDataSelected :{name:"pear",id:"4"}}
<select ng-change="editChangeSelectDatas()"  ng-options="obj.name for obj in selectDatas" ng-model="obj.selectDataSelected"></select>

这样他始终绑定的都是obj对象下的selectDataSelected,就可以避免类似的问题了。
另外使用ng-model双向绑定的时候,建议去绑定他的对象属性比如ng-model=”obj.name”,而不是ng-model=”name”,这样可避免出现此类问题。

4、ng-repeat如何在渲染完成后再去执行脚本

ng-repeat遍历渲染完页面后如何去执行某个操作??接下来需要我们了解一下ng-repeat循环中的几个特殊变量。

扫描二维码关注公众号,回复: 5421564 查看本文章
变量 类型 描述
$index number 当前索引。
$first boolean 当循环的对象存在第一项时为true。
$middle boolean 当循环的对象存在中间项时为true。
$last boolean 当循环对象存在最后一项时为true。
$even boolean 循环的对象在当前位置的索引是偶数则为true。
$odd boolean 循环的对象在当前位置的索引是奇数则为true。

index0 last的值为true,so,通过判断 lastngrepeat last的值:自定义指令

<div id="box">
    <span ng-repeat="item in data" repeat-finish="renderFinish()">{{item.str}}</span>
</div>
app.directive('repeatFinish',function(){
    return {
        link: function(scope,element,attr){
            console.log(scope.$index);
            //也可使用scope.$watch('$last',function(){});
            if(scope.$last == true){
                console.log('ng-repeat执行完毕')
                scope.$eval( attr.repeatFinish )
            }          
        }
    }
})
//controller里对应的处理函数
$scope.renderFinish = function(){
    console.log('渲染完之后的操作')
}

总结:在第一个和第二个问题中反复用到了track by来解决问题,简单了解一下,angular需要一个唯一值可以与生成的dom绑定,以便追踪,因此track by 后面跟的值一定是唯一的,如果一旦出现重复数据,均会保错(包括如果track by 后面的值为undefined,多个undefined也同样会报错),而orderby是可以出现重复数据的,orderby和track by一起使用的格式为:

<tr ng-repeat="item in $ctrl.indicators | orderBy:'id' track by item._id">

提高性能的同时,进行排序。

猜你喜欢

转载自blog.csdn.net/weboof/article/details/79067701
今日推荐