7

我试图了解编译和链接功能之间的区别。在编译器的角度文档中它说

一些指令,例如 ng-repeat 为集合中的每个项目克隆一次 DOM 元素。有一个编译和链接阶段可以提高性能,因为克隆的模板只需要编译一次,然后为每个克隆实例链接一次。

我查看了源代码以尝试了解它是如何工作的,但我不明白它是如何为每个克隆实例创建单独的链接函数的。对我来说,编译函数似乎为 ng-repeat 指令返回了一个链接函数。此链接函数确实为 ng-repeat 中的每个元素创建了一个新范围,但没有为每个克隆实例提供单独的链接函数。

4

2 回答 2

6

One thing that can be confusing about their description is they're trying to discuss the idea of a directive within an <ng-repeat> as opposed to discussing <ng-repeat> itself.

The idea is that even if you have multiple instantiations of a particular directive (for instance because they are within an <ng-repeat>) the compile function is executed once and only once for the lifetime of your app. Thus, the performance benefit of putting code in here is that it only gets run only once. And that's also the potential problem. The only things that should go in a compile function are things that are common to all the instantiations of that directive.

The link function, on the other hand, is executed once for each instantiation of that directive (again, for example, within an <ng-repeat>).

So you can think of the compile function as setting up the template of what a directive of this type should be, while the link function sets up an actual instance of that directive. This is why the link function gets a $scope passed in to it and the compile doesn't and why the link function is the much more commonly used one.

For a great discussion of exactly this by one of the authors of Angular, check out: http://www.youtube.com/watch?v=WqmeI5fZcho&list=TLwY_LmqLDXW_3QKhTNm1zKa9j40TvPO2O (13:42 is where Misko address link vs compile functions)

于 2013-10-19T19:51:26.707 回答
2

除了 KayakDave 的回答,这里是一个简单的 ng-repeat 实现,它不做任何收集观察。plunker 具有显示事件顺序的日志记录,甚至还有一些显示优先级如何工作的示例。

普朗克

链接到源问题

Javascript:

app.directive('fakeRepeat', function() {
  return {
    priority: 1000,
    terminal: true,
    transclude: 'element',
    compile: function(el, attr, linker) {
      return function(scope, $element, $attr) {
        angular.forEach(scope.$eval($attr.fakeRepeat).reverse(), function(x) {
          var child = scope.$new();
          child[attr.binding] = x;
          linker(child, function(clone) {
            $element.after(clone);
          });
        });
      }
    }
  }
});
于 2013-10-19T20:04:31.030 回答