ChatGPT解决这个技术问题 Extra ChatGPT

你对 transclude 函数和 clone 链接函数到底做了什么?

directive Angular docs,我看到编译函数有 3 个参数,其中一个是 transclude。文档提供的唯一解释是:

transclude - 一个 transclude 链接函数:function(scope, cloneLinkingFn)。

我试图了解您在克隆链接功能中究竟会做什么。我什至不知道传递了哪些参数。我发现 one example 有一个名为 clone 的参数,它似乎是一个 HTML 元素。是否有其他可用参数?这到底是哪个 HTML 元素?我也在考虑可能在我的指令中使用 transclude: 'element' 。当使用 'element' 而不是 true 时,这些问题的答案是否会改变?

我通过简单的例子来理解嵌入,但我似乎找不到更复杂的例子,尤其是 transclude: 'element'。我希望有人可以对这一切提供更彻底的解释。谢谢。


6
6 revs, 2 users 99%

编辑:完全完全改变我的答案并将其标记为“社区维基”(对我来说没有积分),因为当我回答这个问题时我完全错了

正如@Jonah 在下面指出的那样,here is a really good article on the compile option of directives and using the transclusion function

基本思想是编译函数应该返回一个链接函数。您可以使用链接函数中提供的嵌入函数来克隆被嵌入的 DOM 元素,对其进行编译,然后将其插入到需要插入的任何位置。

Here is a better example I've pulled out of my butt on Plunker

compile 函数的想法是它让您有机会根据在创建和调用链接函数之前传递的属性以编程方式更改 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);
          }
        });
      };
    }
  };
});

@blesh,我很确定这个答案是错误的。如果您打开控制台并运行您的 plnk,您将看到此错误:TypeError: Cannot read property '1' of null。这是因为您将一个元素传递给 transcludeLinkingFn 的第一个参数,并且它需要一个范围。文档中清楚地说明了这一点:transclude - A transclude linking function: function(scope, cloneLinkingFn). 这样的示例不是预期的用例。 This article 显示一个更好的。
@Jonah:你是 1000% 正确的。我的回答完全错误。这是很久以前的事了,我学得更好了。无论如何,我已经完全改变了答案并将其设置为社区 wiki(没有积分)。
@blesh,我很高兴看到 SO 的一些成员更关心做正确的事情而不是自我。感谢更新!
没有汗水。想到有人遇到这种情况并学会以错误的方式做事,我感到更加羞愧!
只是为了其他来寻找 angular docs 的人包括一些有趣的新事物。 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. 这是因为它预先绑定了范围。