195

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

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

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

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

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

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

4

6 回答 6

523

考虑一个元素中名为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>...and保存<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。

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

于 2013-03-08T16:24:29.137 回答
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>

谢谢。

于 2014-02-05T07:28:07.677 回答
37

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

<div class="something"> This is my directive content <div class="something" ng-transclude></div></div>
于 2015-01-07T09:53:36.897 回答
5

来自维基:

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

我想为嵌入添加另一个用途,那就是它改变了父子指令的编译和链接函数的执行顺序。当您想在父 DOM 之前编译子 DOM 时,这可能很有用,因为父 DOM 可能取决于子 DOM。这篇文章更深入,并且很好地阐明了它!

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

于 2015-04-20T15:30:49.057 回答
5

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

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

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

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


脚本.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';
    }
  };
});

索引.html

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

我的-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 中添加了一个将 name 重新定义为 Jeff 的链接函数。通常,我们希望 {{name}} 是 Jeff。但是,我们在此示例中看到 {{name}} 绑定仍然是 Tobias。

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

于 2017-07-06T05:23:25.977 回答
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.
于 2016-08-27T10:19:21.047 回答