2013-10-19 62 views
7

我想了解編譯和鏈接函數的區別。在the compiler的角度文檔中,它表示AngularJS:ng-repeat的編譯和鏈接函數

某些指令(如ng)重複爲集合中的每個項目克隆DOM元素一次。編譯和鏈接階段提高了性能,因爲克隆模板只需編譯一次,然後爲每個克隆實例鏈接一次。

我看着source code試圖瞭解這是如何工作的,我不明白它如何爲每個克隆實例創建單獨的鏈接函數。對我來說,它看起來像編譯函數返回一個ng-repeat指令的鏈接函數。這個鏈接函數確實爲ng-repeat中的每個元素創建了一個新的作用域,但是並沒有給每個克隆實例一個單獨的鏈接函數。

回答

6

有一點可以混淆描述的是他們試圖在<ng-repeat>討論指令的想法,而不是討論<ng-repeat>本身。

這個想法是,即使你有一個特定指令的多個實例(例如因爲它們在<ng-repeat>之內),編譯功能在你的應用程序的整個生命週期中只執行一次。因此,將代碼放在這裏的性能好處是它只能運行一次。這也是潛在的問題。編譯函數中唯一需要做的事情就是該指令的所有實例都是通用的。

另一方面,對於該指令的每個實例(例如,在<ng-repeat>內),鏈接函數都會執行一次。

所以你可以把編譯函數想象成設置這種類型的指令應該是什麼樣的模板,而鏈接函數設置該指令的實際實例。這就是爲什麼鏈接函數得到一個$範圍傳遞給它,並且編譯沒有,以及爲什麼鏈接函數是更常用的。

對於由折角的作者之一正是這個偉大的討論,請上網:http://www.youtube.com/watch?v=WqmeI5fZcho&list=TLwY_LmqLDXW_3QKhTNm1zKa9j40TvPO2O(13:42就是MISKO地址鏈接VS編譯功能)

+0

謝謝您的回答和紐帶,他們肯定幫了不少忙。只是爲了確保正確理解,如果您要在元素上使用ng-repeat指令,您似乎只會使用編譯。否則,你可以使用鏈接功能做所有事情,所以使用編譯沒有真正的好處。 – jvans

+0

我想你明白了。除了你有多個指令副本的情況。 ng-repeat只是描述這種情況的一種便利方式。 – KayakDave

+0

而在這兩種情況下,鏈接仍然是更常用的功能。正如你所說,你可以使用鏈接功能做更多的事情,因爲它被附加到一個真正的範例的實例。 – KayakDave

2

在addtion到KayakDave的答案,這裏是一個簡單ng-repeat的實現不會執行任何收集觀察。這位笨蛋的日誌記錄顯示了事件的順序,甚至有一些例子顯示了優先級如何工作。

Plunker

Link to source question

的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); 
      }); 
     }); 
     } 
    } 
    } 
});