理解指令定义的transclude选项?

时间:2013-03-08 14:28:51

标签: angularjs angularjs-directive

我认为这是我用angularjs指令理解的最难的概念之一。

来自http://docs.angularjs.org/guide/directive的文件说:

  

transclude - 编译元素的内容并使其可用于指令。通常与ngTransclude一起使用。翻译的优点是链接功能接收预先绑定到正确范围的翻译功能。在典型的设置中,窗口小部件创建隔离范围,但是转换不是子项,而是隔离范围的兄弟。这使得窗口小部件可以具有私有状态,并且将转换绑定到父(预隔离)范围。

     
      
  • true - 转换指令的内容。
  •   
  • 'element' - 转换整个元素,包括以较低优先级定义的任何指令。
  •   

它说transclude通常与ngTransclude一起使用。但是来自ngTransclude文档的示例根本不使用ngTransclude指令。

我想要一些很好的例子来帮助我理解这一点。我们为什么需要它?它解决了什么?怎么用?

6 个答案:

答案 0 :(得分:494)

在元素中考虑一个名为 myDirective 的指令,该元素包含一些其他内容,比方说:

<div my-directive>
    <button>some button</button>
    <a href="#">and a link</a>
</div>

如果 myDirective 正在使用模板,您会看到<div my-directive>的内容将被您的指令模板替换。所以:

app.directive('myDirective', function(){
    return{
        template: '<div class="something"> This is my directive content</div>'
    }
});

将导致此渲染:

<div class="something"> This is my directive content</div> 

请注意,原始元素<div my-directive> 的内容将丢失(或更好地说,替换)。所以,告别这些伙伴们:

<button>some button</button>
<a href="#">and a link</a>

那么,如果您希望将<button>...<a href>...保留在DOM中,该怎么办?你需要一些叫做翻译的东西。这个概念非常简单:将内容从一个地方包含到另一个地方。所以现在你的指令看起来像这样:

app.directive('myDirective', function(){
    return{
        transclude: true,
        template: '<div class="something"> This is my directive content</div> <ng-transclude></ng-transclude>'
    }
});

这将呈现:

<div class="something"> This is my directive content
    <button>some button</button>
    <a href="#">and a link</a>
</div>. 

总之,当您想要在使用指令时保留元素的内容时,基本上使用transclude。

我的代码示例是here。 观看this也可以获益。

答案 1 :(得分:75)

我认为在新版本的AngularJS中提及上述行为的变化非常重要。我花了一个小时试图用Angular 1.2.10获得上述结果。

带有ng-transclude的元素的内容不会被附加,但会被完全替换。

所以在上面的例子中,你用'transclude'实现的目标是:

<div class="something">
    <button>some button</button>
    <a href="#">and a link</a>
</div>

而不是

<div class="something"> This is my directive content
    <button>some button</button>
    <a href="#">and a link</a>
</div>

感谢。

答案 2 :(得分:36)

TechExplorer所说的是正确的,但您可以通过在模板中包含带有ng-transclude属性的简单容器标记(如div或span)来同时拥有这两个内容。这意味着模板中的以下代码应包含所有内容

<div class="something"> This is my directive content <div class="something" ng-transclude></div></div>

答案 3 :(得分:5)

来自维基:

  

“在计算机科学中,包含部分或全部包含在内   通过引用将电子文件分成一个或多个其他文件。“

我想添加另一个用于转义的用法,那就是它改变了父指令和子指令的编译和链接函数的执行顺序。当您想在父DOM之前编译子DOM时,这可能很有用,因为父DOM可能依赖于子DOM。本文更深入,更清楚地阐明了它!

http://www.jvandemo.com/the-nitty-gritty-of-compile-and-link-functions-inside-angularjs-directives-part-2-transclusion/

答案 4 :(得分:3)

Updated AngularJS 1.6.6 documentation现在有更好的解释。

Transclude用于创建包含其他元素的指令

有时候能够传入整个模板而不是字符串或对象是可取的。让我们说我们想创建一个&#34;对话框&#34;零件。该对话框应该能够包装任意内容。

为此,我们需要使用转换选项。请参阅下面的示例。

的script.js

angular.module('docsTransclusionExample', [])
.controller('Controller', ['$scope', function($scope) {
  $scope.name = 'Tobias';
}])
.directive('myDialog', function() {
  return {
    restrict: 'E',
    transclude: true,
    scope: {},
    templateUrl: 'my-dialog.html',
    link: function(scope) {
      scope.name = 'Jeff';
    }
  };
});

的index.html

<div ng-controller="Controller">
  <my-dialog>Check out the contents, {{name}}!</my-dialog>
</div>

MY-dialog.html

<div class="alert" ng-transclude></div>

编译输出

<div ng-controller="Controller" class="ng-scope">
  <my-dialog class="ng-isolate-scope"><div class="alert" ng-transclude="">Check out the contents, Tobias!</div></my-dialog>
</div>

Transclude使得带有此选项的指令的内容可以访问指令之外的范围而不是内部。

这在前面的例子中说明。请注意,我们在script.js中添加了一个链接函数,该函数将名称重新定义为Jeff。通常,我们希望{{name}}是杰夫。但是,我们在此示例中看到{{name}}绑定仍然是Tobias。

最佳实践:当您要创建包含任意内容的指令时,仅使用transclude: true

答案 5 :(得分:0)

transclude:true表示使用指令的template元素添加指令中定义的所有元素。

如果transclude:false这些元素不包含在最终的html指令中,只会呈现指令模板。

transclude:element表示您的指令模板不仅用于定义的元素 在你的指令中呈现为html。

当您定义指令时,它应该限制为E,当您在页面上添加它时

<my-directive><elements><my-directive>
<elements> is like <p>gratitude</p>
what i am talking about.