angularjs – 保持角度的观察者? (ng-repeat POV)

我已经知道了如何处理ng-repeat性能问题(与观察者一起)的常见模式,如:一次性绑定,无限滚动等.

但我看到这个answer的人建议转向指令.

好的,我开始采用简单的旧方法

Approach #1’s plunker:

这个html有100个项目:

  <div ng-repeat="e in ct.arr">
      <div class='s'> 
        <span >name:{{e.name}} , age:{{e.age}} , height:{{e.height}}</span>
      <hr>
  </div>

这将产生301个观察者,当我点击一个按钮时我可以更改第5个项目:

《angularjs – 保持角度的观察者? (ng-repeat POV)》

那么我想把它移到指令(就像建议的那样):

Approaches #2’s plunker

现在HTML是:

 <div ng-repeat="e in ct.arr">
     <div class='s'> 
        <span  my-event="e" ></span>
      <hr>
    </div>
  </div>

指令:

.directive('myEvent', function() {
  return {
    scope: {
      event: "=myEvent"
    },
    link: link,
   }

  function link(scope, element, attrs) {
     var ev = scope.event;
     element.text('name:'+ev.name +', age:'+ev.age+' , height:'+ev.height)
  }
});

现在我只有101名观察者,但现在按钮没有影响:

《angularjs – 保持角度的观察者? (ng-repeat POV)》

问题:

>如果我是对的,100名观察者是因为孤立范围的直接别名是通过’=’.但如果它是该项目的直接别名,为什么我没有看到按钮点击后的修改?
>如果我想看到修改,我是否被301观察员困扰?还有什么我没有想到的 – 可以做到吗?

最佳答案 像Alainlb写的那样,你只是在创建时计算内容一次.当然就像你在评论中写一样,使用模板:’< span>名称:{{event.name}},年龄:{{event.age}},身高:{{event.height}}&lt ; /跨度>”添加手表(每个{{…}}是幕后的手表).

想到的第一个解决方案是使用监视指令的项目.深度监视具体,以便它可以检测对象属性的更改,而不仅仅是对实际对象引用的更改:

function link(scope, element, attrs) {
    scope.$watch('event', function(ev) {
        element.text('name:' + ev.name + ', age:' + ev.age + ' , height:' + ev.height);
    }, true);
}

http://plnkr.co/edit/marpxMx5qin7mOlFwp3X?p=preview

分数:201手表

但我们可以做得更好;因为我们正在手动观察,所以= scope绑定现在是多余的.哦,然后范围:{}配置为空;我们甚至可以没有范围,既不是孤立的,也不是新的原型继承的.让我们使用scope:false(每次迭代可以节省1个范围对象,对于许多迭代来说都是很好的增益).

我们现在直接观察my-event属性中给出的表达式:

.directive('myEvent', function() {
    return {
        scope: false,
        link: link,
    };

    function link(scope, element, attrs) {
        scope.$watch(
            attrs.myEvent,
            function(ev) {
                element.text('name:' + ev.name + ', age:' + ev.age + ' , height:' + ev.height);
            },
            true
        );
    }
});

http://plnkr.co/edit/lvnIQCJMnniFlOeRseaZ?p=preview

分数:101手表

有一个问题:深度观察产生较少的手表,但它们更昂贵,因为它们迭代观察对象的每个属性.因此,真正的性能提升可能会低于它看起来的效果 – 101手表对301手表.我们可以做得更好吗?

在尝试之前,我首先要测量101深表和301表之间的真正性能差异.如果可以忽略不计,我们没关系.否则,我们可能会使用Javascript属性getter和setter在我们的更新中变得“更聪明”,并且可能在对象上手动设置脏标志.这将很复杂.

更好的方法是永远不要改变对象的内部属性(将其视为不可变 – 一般来说是一个好主意)并更改引用本身.即做:

vm.c10 = function (){
    this.arr[4] = {
        name: "aaaa",
        age: "aaaa",
        height: "aaaa"
    };
};

然后你不再需要深入观察(从范围的参数中删除,true.$watch).如果你可以强制执行对象是不可变的约定(Immutable.js任何人?),你是独自工作,或者团队(现在和将来)与这个约定有良好的沟通和理解,那么这种方法效果最好.否则就会出现邪恶的错误.

点赞