2013-08-23 41 views
3

在我的理解中,$ compile應該能夠支持嵌套指令編譯/鏈接,但是我們遇到了編譯/鏈接不完整的問題 - 只有最外面的指令被渲染到DOM ,這個問題只有當再現雙雙跌破條件都爲真:爲什麼AngularJS指令編譯不支持嵌套指令

  1. 內部指令模板通過templateUrl加載(如異步方式)
  2. 編譯觸發角外的情況下。

我編譯後的地方寫了jsfiddler演示它,下面列出部分代碼,完整的情況下http://jsfiddle.net/pattern/7KjWP/

myApp.directive('plTest', function($compile){ 
return { 
    restrict :'A', 
    scope: {}, 
    replace: true, 
    template: '<div>plTest rendered </div>', 
    link: function (scope, element){ 
     $('#button1').on('click', function(){ 
      var ele; 
      ele = $compile('<div pl-shared />')(scope); 
      console.log('plTest compile got : '+ ele[0].outerHTML); 
      // scope.$apply(); 
      element.append(ele); 
     }); 
    } 
}; 
}); 

myApp.directive('plShared', function($compile, $timeout){ 
return { 
    restrict: 'A', 
    scope: {}, 
    replace: true, 
    link: function (scope, element){ 
     // comment out below line to make render success 
     //$timeout(function(){}); 
     var el = $compile('<div pl-item></div>')(scope); 
     console.log('plShared compile got:' + el[0].outerHTML); 
     element.append(el); 
    } 
}; 
}); 

myApp.directive('plItem', function($timeout){ 
return { 
    restrict: 'A', 
    scope:{}, 
    template:'<div>plItem rendered <div pl-avatar/></div>', 
    link: function(scope){    

    } 
}; 
}); 

myApp.directive('plAvatar', function(){ 
return { 
    restrict: 'A', 
    scope: {} 
    , templateUrl: 'avatar.html' 
    // ,template: 'content of avatar.html <div pl-image></div>' 
}; 
}); 

有趣的是,我可以通過調用範圍內解決該問題。$適用()( )調用(第27行) 或將$ timeout(function(){})調用添加到內部指令(第41行)之一的鏈接func中。這是缺陷還是設計?

+0

這就是雙向綁定的工作原理,您可以在Angular上下文中進行更改,或者您必須自己調用$ apply()。 – user2172816

+0

@stevuu解釋它,你的代碼中的實際問題是這樣一行:'$('#button1')。on('click',..' - 角度不知道這個事件是由你的代碼處理,除非你調用'$ scope。$ apply()' – package

+0

我知道有必要調用範圍。$ apply()在角上下文之外爲了推出$ evalAsyc和$ watch檢查,但是令我困惑的是爲什麼指令編譯有一些猜測可能是模板以異步方式加載,並且在所有asyc加載完成之前角度可能沒有機會鏈接所有模板,因此需要$ apply()來顯式地解析那些加載promise從$ evalAsyc隊列,如果這是真的,那麼有額外的$ apply()是合理的,否則不一致是有點煩人。 –

回答

3

$(foo).on(bar, handler)是一個jQuery事件,這意味着AngularJS不知道它的具體細節,並且在它處理完所有綁定後不會(不能)運行apply-digest cycle

scope.$apply是爲此做出的,正如你所說的那樣,修正了它。經驗法則是:如果您在使用其他庫的AngularJS應用程序中實現UI功能(特別是:在應用摘要循環之外),則必須自己調用scope.$apply

HTH!

0

在element.append(el)之後,嘗試重新編譯,因爲您剛剛修改了DOM。

你可以試試諸如$compile(element)(scope);$compile(element.contents())(scope);

正如我以前說過,我也會改變事件處理程序如下:

$('#button1').on('click', function(){ 
    scope.$apply(function(){ 
      //blablalba 
    }); 
}); 

此外,胡斯塔忠告的情況下,你會希望來縮小你的代碼,我會使用聲明編譯依賴語法如下:

.directive('directiveName',['$service1',''$service2,...,'$compile', function($service1, $service2,...,$compile){ 
    //blablabla 
}]}