$compile 和$link

實際上link其實是由$compile生成的函數,而且這個函數在生成的時候內容已經定好了,所以在調用link函數的時候只是傳對應的scope參數給這些由$compile編譯好的link函數,所以如果想通過cloneAttachFn這個傳入link的回調函數來修改dom結構是不行的。

$compile 最基本的使用方式:

var link = $compile('<p>{{ text }}</p>');
var node = link($scope);
console.log(node);

上面的 $compile 和 link 調用時都有額外參數來實現其它功能。先看 link 函數,它形如:

function(scope[, cloneAttachFn]

第二個參數 cloneAttachFn 的作用是,表明是否複製原始節點,及對複製節點需要做的處理,下面這個例子說明了它的作用:

<div ng-controller="TestCtrl"></div>
<div id="a">A {{ text }}</div>
<div id="b">B </div>
app.controller('TestCtrl', function($scope, $compile){
  var link = $compile($('#a'));

  //true參數表示新建一個完全隔離的scope,而不是繼承的child scope
  var scope = $scope.$new(true);
  scope.text = '12345';

  //var node = link(scope, function(){});
  var node = link(scope);

  $('#b').append(node);
});

cloneAttachFn 對節點的處理是有限制的,你可以添加 class ,但是不能做與數據綁定有關的其它修改(修改了也無效):

app.controller('TestCtrl', function($scope, $compile){
  var link = $compile($('#a'));
  var scope = $scope.$new(true);
  scope.text = '12345';

  var node = link(scope, function(clone_element, scope){
    clone_element.text(clone_element.text() + ' ...'); //無效
    clone_element.text('{{ text2 }}'); //無效
    clone_element.addClass('new_class');
  });

  $('#b').append(node);
});

修改無效的原因是,像 {{ text }} 這種所謂的 Interpolate 在 $compile 中已經被處理過了,生成了相關函數(這裏起作用的是 directive 中的一個 postLink 函數),後面執行 link 就是執行了$compile 生成的這些函數。當然,如果你的文本沒有數據變量的引用,那修改是會有效果的。

前面在說自定義指令時說過, link 函數是由 compile 函數返回的,也就像前面說的,應該把改變 DOM 結構的邏輯放在 compile 函數中做。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章