了解指令定义的transclude选项吗?


195

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

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

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

  • true-包含指令的内容。
  • 'element'-包括整个元素,包括以较低优先级定义的所有指令。

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

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


仅供参考...链接至少现在正在工作
Sandy

Answers:


518

考虑在一个元素中一个名为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。

我的代码示例在这里。你也可以受益于看这个


12
好像他们已经稍微改变了功能。至少>> 1.2.9版本。模板中的内容不会添加到渲染的内容中。请参阅下面的@TechExplorer答案
Tarjei Romtveit 2014年

20
一个非常非常好的答案。远高于正常水平。您有很好的示例,并且“这是我的指令内容”使得在呈现的版本中非常容易阅读。我不明白为什么Angular必须使用复杂的术语和概念,然后不包括像您这样的易于理解的示例。+2
freeall 2015年

有谁知道被包含的内容是否可以引用指令的隔离范围字段?它说,上面说的是transclusion兄弟姐妹,没有一个孩子,分离范围的...所以我假设它不能-但不知道是否有人能证实或让我知道,如果可能的话
西蒙绿

@UladzimirHavenchyk谢谢,他们将视频移到了其他地方。我相应地修复了链接。
odiseo

4
@odiseo,您能以简单,易懂的英语编写所有Angular文档吗?+很多1。
Dan Hodson

76

我认为重要的是要在新版本的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>

谢谢。


有关Angular 1.2中已更改行为的更多信息,请参见change eed299a
Mark Rajcok

37

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

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

5
那是其他答案上所缺少的关键信息
Matheus

4
这个答案增加了很多信息。ng-transclude是充当占位符的属性,将在其中放置被排除的内容。
BeingSuman

5

从Wiki:

“在计算机科学中,包含是指通过引用将一部分或全部电子文档包含到一个或多个其他文档中。”

我想为包含添加另一种用途,那就是它更改了父指令和子指令的编译和链接功能的执行顺序。当您要在父DOM之前编译子DOM时,这很有用,因为父DOM可能取决于子DOM。本文更深入地进行了阐述,并做了很好的说明!

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


5

现在,更新的AngularJS 1.6.6文档有了更好的解释。

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

有时,希望能够传递整个模板而不是字符串或对象。假设我们要创建一个“对话框”组件。该对话框应该能够包装任意内容。

为此,我们需要使用transclude选项。请参考以下示例。


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}}是Jeff。但是,在此示例中,我们看到{{name}}绑定仍然是Tobias。

最佳实践:仅transclude: true在要创建包装任意内容的指令时使用。


0

transclude:true表示将指令中定义的所有元素与指令的模板元素相加。

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

transclude:element表示不使用指令模板,只有指令中定义的元素才呈现为html。

当您定义指令时,则应将其限制为E,然后在页面上添加该指令时

<my-directive><elements><my-directive>
<elements> is like <p>gratitude</p>
what i am talking about.
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.