$ digest渲染ng-repeat作为评论

Aba*_*aco 6 javascript unit-testing angularjs angularjs-directive

我正在为一个指令编写测试,在执行测试时,模板(正确加载)的渲染就像 <!-- ng-repeat="foo in bar" -->

对于初学者来说,代码的相关部分:

测试

...

beforeEach(inject(function ($compile, $rootScope, $templateCache) {

    var scope = $rootScope;
    scope.prop = [ 'element0', 'element1', 'element2' ];

    // Template loading, in the real code this is done with html2js, in this example
    // I'm gonna load just a string (already checked the problem persists)
    var template = '<strong ng-repeat="foo in bar"> <p> {{ foo }} </p> </strong>';
    $templateCache.put('/path/to/template', [200, template, {}]);

    el = angular.element('<directive-name bar="prop"> </directive-name>');
    $compile(el)(scope);
    scope.$digest(); // <--- here is the problem
    isolateScope = el.isolateScope();

    // Here I obtain just the ng-repeat text as a comment
    console.log(el); // <--- ng-repeat="foo in bar" --> 
}));

...
Run Code Online (Sandbox Code Playgroud)

指示

该指令相当简单,并不是问题(在测试之外一切正常):

app.directive('directiveName', function () {
    return {
        restrict : 'E',
    replace : true,
    scope : {
        bar : '='
    },
    templateUrl : '/path/to/template', // Not used in this question, but still...
});
Run Code Online (Sandbox Code Playgroud)

更多细节:

  • 在测试之外,该指令工作正常
  • 如果我将模板更改为更简单的东西:<h3> {{ bar[0] }} </h3>测试工作正常
  • rootScope已正确加载
  • isolateScope结果如下 undefined

mic*_*ael 2

如果您查看 Angular 创建的生成输出,ng-repeat您会在 html 中找到注释。例如:

<!-- ngRepeat: foo in bars  -->
Run Code Online (Sandbox Code Playgroud)

这些注释是由编译函数创建的 - 请参阅角度源:

document.createComment(' ' + directiveName + ': '+templateAttrs[directiveName]+' ')
Run Code Online (Sandbox Code Playgroud)

如果你打电话,你会得到的console.log(el);是创建的评论。如果您以这种方式更改输出,您可以检查这一点:console.log(el[0].parentNode)。你会看到有很多子节点: 在此输入图像描述

如果您在测试之外使用该指令,您将不会意识到这个问题,因为您的元素directive-name将被完整创建的DocumentFragment. 解决该问题的另一种方法是为指令模板使用包装元素:

<div><strong ng-repeat="foo in bar"> <p> {{ foo }} </p> </strong></div>
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您可以访问该div元素。