Angular 指令中的递归 [英] Recursion in Angular directives

查看:22
本文介绍了Angular 指令中的递归的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有几个流行的递归角度指令问答,它们都归结为以下解决方案之一:

There are a couple of popular recursive angular directive Q&A's out there, which all come down to one of the following solutions:

  • 根据运行时范围状态手动增量编译"HTML
    • manually incrementally 'compile' HTML based on runtime scope state
      • example 1 [stackoverflow]
      • example 2 [angular jsfiddles page]

      第一个的问题是,除非您对手动编译过程进行了全面的管理,否则您无法删除以前编译的代码.第二种方法的问题是...不是指令并错过了其强大的功能,但更紧迫的是,它不能像指令一样参数化;它只是绑定到一个新的控制器实例.

      The first one has the problem that you can't remove previously compiled code unless you comprehensibly manage the manual compile process. The second approach has the problem of... not being a directive and missing out on its powerful capabilities, but more urgently, it can't be parameterised the same way a directive can be; it's simply bound to a new controller instance.

      我一直在尝试在链接函数中手动执行 angular.bootstrap@compile() ,但这给我留下了手动跟踪的问题要删除和添加的元素.

      I've been playing with manually doing an angular.bootstrap or @compile() in the link function, but that leaves me with the problem of manually keeping track of elements to remove and add.

      有没有一种好的方法来管理添加/删除元素以反映运行时状态的参数化递归模式?也就是说,带有添加/删除节点按钮和一些输入字段的树,其值向下传递节点的子节点.也许是第二种方法与链式作用域的结合(但我不知道如何做到这一点)?

      Is there a good way to have a parameterized recursive pattern that manages adding/removing elements to reflect runtime state? That is to say, a tree with a add/delete node button and some input field whose value is passed down a node's child nodes. Perhaps a combination of the second approach with chained scopes (but I have no idea how to do this)?

      推荐答案

      受到@dnc253 提到的线程中描述的解决方案的启发,我抽象了递归功能进入服务.

      Inspired by the solutions described in the thread mentioned by @dnc253, I abstracted the recursion functionality into a service.

      module.factory('RecursionHelper', ['$compile', function($compile){
          return {
              /**
               * Manually compiles the element, fixing the recursion loop.
               * @param element
               * @param [link] A post-link function, or an object with function(s) registered via pre and post properties.
               * @returns An object containing the linking functions.
               */
              compile: function(element, link){
                  // Normalize the link parameter
                  if(angular.isFunction(link)){
                      link = { post: link };
                  }
      
                  // Break the recursion loop by removing the contents
                  var contents = element.contents().remove();
                  var compiledContents;
                  return {
                      pre: (link && link.pre) ? link.pre : null,
                      /**
                       * Compiles and re-adds the contents
                       */
                      post: function(scope, element){
                          // Compile the contents
                          if(!compiledContents){
                              compiledContents = $compile(contents);
                          }
                          // Re-add the compiled contents to the element
                          compiledContents(scope, function(clone){
                              element.append(clone);
                          });
      
                          // Call the post-linking function, if any
                          if(link && link.post){
                              link.post.apply(null, arguments);
                          }
                      }
                  };
              }
          };
      }]);
      

      用法如下:

      module.directive("tree", ["RecursionHelper", function(RecursionHelper) {
          return {
              restrict: "E",
              scope: {family: '='},
              template: 
                  '<p>{{ family.name }}</p>'+
                  '<ul>' + 
                      '<li ng-repeat="child in family.children">' + 
                          '<tree family="child"></tree>' +
                      '</li>' +
                  '</ul>',
              compile: function(element) {
                  // Use the compile function from the RecursionHelper,
                  // And return the linking function(s) which it returns
                  return RecursionHelper.compile(element);
              }
          };
      }]);
      

      有关演示,请参阅此 Plunker.我最喜欢这个解决方案,因为:

      See this Plunker for a demo. I like this solution best because:

      1. 你不需要一个特殊的指令来让你的 html 变得不那么干净.
      2. 递归逻辑被抽象到 RecursionHelper 服务中,因此您可以保持指令干净.

      更新:从 Angular 1.5.x 开始,不再需要任何技巧,但仅适用于 template,不适用于 templateUrl

      Update: As of Angular 1.5.x, no more tricks are required, but works only with template, not with templateUrl

      这篇关于Angular 指令中的递归的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆