3

在我的理解中,$compile 应该能够支持嵌套指令编译/链接,但是我们遇到了编译/链接不完整的问题——只有最外层的指令被渲染到 DOM 中,并且只有在以下两种情况下才会重现该问题真的:

  1. 内部指令模板通过 templateUrl 加载(例如异步方式)
  2. 编译是在 Angular 上下文之外触发的。

我写了一个 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>'
};
});

有趣的是,我可以通过在 compile() 调用(第 27 行)之后的某处调用 scope.$apply() 或将 $timeout(function(){}) 调用添加到内部指令之一的链接函数中(第 41 行)来解决这个问题)。这是缺陷还是设计使然?

4

2 回答 2

3

$(foo).on(bar, handler)是一个 jQuery 事件,这意味着 AngularJS 不知道它的细节,并且不会(不能)在它处理所有绑定之后运行应用摘要循环。

scope.$apply是为此而设计的,正如你所说的,修复它。经验法则是:如果您使用其他库在 AngularJS 应用程序中实现 UI 功能(特别是:在应用摘要周期之外),您必须调用scope.$apply自己。

于 2013-08-23T06:56:53.583 回答
0

在 element.append(el) 之后,尝试再次编译,因为您刚刚修改了 DOM。

您可以尝试诸如$compile(element)(scope);or之类的东西$compile(element.contents())(scope);

正如我之前所说,我还将按如下方式更改事件处理程序:

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

另外,如果您想缩小代码,只是一个建议,我将使用以下语法声明编译依赖项:

.directive('directiveName',['$service1',''$service2,...,'$compile', function($service1, $service2,...,$compile){
     //blablabla
}]}
于 2013-08-28T15:45:44.530 回答