AngularJS:通过递归指令手动 $compile 与自然 $compile

标签 angularjs recursion compilation directive

我试图用 AngularJS 创建我自己的递归指令,它调用自己以漂亮的 JSON 格式转换 View 中的对象。好吧,首先我使用 ng-include 调用带有模板的脚本,在其中使用 ng-if 验证当前值是否是一个对象,如果是,则模板调用本身。

我一直认为这是一种糟糕的方法,所以我转换为一个指令,更简单。

越来越少......因为我发现了递归指令的世界,发现了很多东西,而且最有趣。我什至在 github 中阅读了 Angular 的源代码(我建议你阅读:https://github.com/angular/angular.js),这是一件好事。

我努力寻找,我想我几乎找到了会珍惜我的心的awser!因为我学到了很多新东西,你们会帮助我。

在下面的链接中查看我的代码:https://github.com/Daymannovaes/htmljs/blob/master/js/directives/recursiveDataTemplateDirective.js

我的指令是:recursive-data-template="data",其中数据是一个对象。该指令将遍历该对象的键和值,如果该值是一个对象,将再次执行此操作。条件由 ng-if="isObject(value)"构成。

好的,我的第一个问题是无限循环。我需要在编译阶段删除内容,然后在 postLink 阶段强制编译内容。我的问题:
** 为什么手动编译不会遇到同样的死循环问题? **

我正在编译相同的内容,没有条件(如果 if(!compiledContent) 被删除,无限循环仍然没有发生),差异(我认为)只是它们是在不同的地方制作的,但我没有无法在互联网上找到对我的问题提出质疑的人!

所以谢谢!
(如果链接不起作用,这里是重要的代码):

compile: function(templateElement, templateAttributes) {
            /*
              in compile time, we need to remove the innerHTML of template(url) because of its recursive.
              Because of its recusiveness, when the $compile start to read the DOM tree and find a
              recursiveDataTemplate directive (even its not will be evaluated all time by link function
              because the ng-if, whatever) its start the do all the process again. So, we need the .remove()
             */
            var templateDirectiveContent = templateElement.contents().remove();
            var compiledContent;

            return function($scope, linkElement, linkAttributes) {

                /* 
                  This verification avoid to compile the content to all siblings, because
                  when you compile the siblings, don't work (I don't know why, yet).
                  So, doing this we get only the top level link function (from each iteration)
                 */
                if(!compiledContent) {
                    compiledContent = $compile(templateDirectiveContent);
                }

                /*
                  Calling the link function passing the actual scope we get a clone object
                  wich contains the finish viewed object, the view itself, the DOM!!
                  Then, we attach the new dom in the element wich contains the directive
                 */
                compiledContent($scope, function(clone) {
                  linkElement.append(clone); 
                });
            };
        },
  }

<ul>
    <li data-ng-repeat="(key, value) in fields">
        <span data-ng-if="!isNumber(key)">
            {{key}}:
        </span>

        <span data-ng-if="isObject(value)" recursive-data-template="value"></span>

        <span data-ng-if="!isObject(value)">
            {{value}}
        </span>

    </li>
</ul>

最佳答案

我相信这篇摘自 official documentation 与您要问的有关:

Note: The compile function cannot handle directives that recursively use themselves in their own templates or compile functions. Compiling these directives results in an infinite loop and a stack overflow errors. This can be avoided by manually using $compile in the postLink function to imperatively compile a directive's template instead of relying on automatic template compilation via template or templateUrl declaration or manual compilation inside the compile function.



从您提供的代码来看,您似乎已经完成了此注释的建议 - 也就是说,在您为 compile 返回的函数 (postLink) 中手动编译您的指令的属性。

关于AngularJS:通过递归指令手动 $compile 与自然 $compile,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24113357/

相关文章:

javascript - 将输入字段中的字符限制为一组字符

angularjs - Webpack 不处理 Controller 中模板中的 pug 文件

c++ - 具有返回类型 node* 的函数与 C++ 中的 OOP 结合使用

java - 如何在java中为堆编写递归trickleUp方法?

c++ - 如何将 cpp 源编译为完整的静态二进制文件,但 : libc, libpthread、libdl、libstdc++ 和 libm 除外

angularjs - 作用域变量仅在第一次更新

angularjs - 带有 RequireJs 的 Angular-Material

c - 算法的递归关系

compiler-errors - CUDA 在编译期间无法识别 nvcuda 命名空间

python - 如何将python脚本编译为二进制可执行文件