您究竟如何使用transclude函数和克隆链接函数?


70

Angular docs指令中,我看到compile函数具有3个参数,其中一个是transclude。该文档提供的唯一解释是:

transclude-包含链接的函数:function(scope,cloneLinkingFn)。

我试图了解您将在克隆链接功能中执行的操作。我什至不知道将哪些参数传递给它。我发现了一个示例,该示例的一个参数clone似乎是一个HTML元素。还有其他可用参数吗?这到底是哪个HTML元素?我也在寻找可能transclude: 'element'在我的指令中使用。执行这些问题的答案时,用改变'element'来代替true

我通过简单的示例理解了包含,但似乎找不到更复杂的示例,尤其是使用transclude: 'element'。我希望有人可以对此提供更详尽的解释。谢谢。

Answers:


55

编辑。

就像@Jonah在下面指出的那样,这是一篇关于伪指令的编译选项和使用包含函数的非常好的文章。

基本思想是编译函数应返回链接函数。您可以使用链接功能内部提供的包含功能来获取包含对象的DOM元素的副本,进行编译,然后将其插入需要插入的位置。

这是一个更好的例子,我已经摆脱了对Plunker的支持

编译函数的思想是,您可以在创建和调用链接函数之前,根据传递的属性以编程方式更改DOM元素。

// a silly directive to repeat the items of a dictionary object.
app.directive('keyValueRepeat', function ($compile){
  return {
    transclude: true,
    scope: {
      data: '=',
      showDebug: '@'
    },
    compile: function(elem, attrs, transclude) {

      if(attrs.showDebug) {                
        elem.append('<div class="debug">DEBUG ENABLED {{showDebug}}</div>');
      }

      return function(scope, lElem, lAttrs) {
        var items = [];
        console.log(lElem);
        scope.$watch('data', function(data) {

          // remove old values from the tracking array
          // (see below)
          for(var i = items.length; i-- > 0;) {
            items[i].element.remove();
            items[i].scope.$destroy();
            items.splice(i,1);
          }

          //add new ones
          for(var key in data) {

            var val = data[key],
                childScope = scope.$new(),
                childElement = angular.element('<div></div>');

            // for each item in our repeater, we're going to create it's
            // own scope and set the key and value properties on it.
            childScope.key = key;
            childScope.value = val;

            // do the transclusion.
            transclude(childScope, function(clone, innerScope) {
              //clone is a copy of the transcluded DOM element content.
              console.log(clone);

              // Because we're still inside the compile function of the directive,
              // we can alter the contents of each output item
              // based on an attribute passed.
              if(attrs.showDebug) {                
                clone.prepend('<span class="debug">{{key}}: {{value}}</span>');
              }

              //append the transcluded element.
              childElement.append($compile(clone)(innerScope));
            });

            // add the objects made to a tracking array.
            // so we can remove them later when we need to update.
            items.push({
              element: childElement,
              scope: childScope
            });

            lElem.append(childElement);
          }
        });
      };
    }
  };
});

3
@blesh,我敢肯定这个答案是错误的。如果打开控制台并运行plnk,则会看到此错误:TypeError: Cannot read property '1' of null。这是因为您正在将元素传递到transcludeLinkingFn的第一个参数中,并且它需要一个范围。在文档中清楚地说明了transclude - A transclude linking function: function(scope, cloneLinkingFn). 这一点:此类示例不是预期的用例。 本文显示了一个更好的。
约拿(Jonah)

9
@乔纳:你是正确的1000%。我的回答是完全错误的。这是前一段时间,我学得更好。无论如何,我已经完全改变了答案,并将其设置为社区Wiki(未授予分数)。
本·拉什

17
@blesh,我很高兴看到SO的某些成员更关心正确的事情而不是自我。感谢您的更新!
约拿(

10
没汗 想到有人发现了这种错误,并学会了以错误的方式去做某事,我感到非常愧!
本·拉什

4
仅对于其他来找有角度文档的人来说,其中包含一些有趣的新事物。 Note: The transclude function that is passed to the compile function is deperecated, as it e.g. does not know about the right outer scope. Please use the transclude function that is passed to the link function instead. 这是因为它具有预先绑定的范围。
2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.