理解指令定义的transclude选项?

Fre*_*ind 189 angularjs angularjs-directive

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

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

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

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

transclude通常用于ngTransclude.但是来自ngTransclude文档的样本根本不使用ngTransclude指令.

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

odi*_*seo 505

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

<div my-directive>
    <button>some button</button>
    <a href="#">and a link</a>
</div>
Run Code Online (Sandbox Code Playgroud)

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

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

将导致此渲染:

<div class="something"> This is my directive content</div> 
Run Code Online (Sandbox Code Playgroud)

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

<button>some button</button>
<a href="#">and a link</a>
Run Code Online (Sandbox Code Playgroud)

那么,如果你想保留你的DOM <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>'
    }
});
Run Code Online (Sandbox Code Playgroud)

这将呈现:

<div class="something"> This is my directive content
    <button>some button</button>
    <a href="#">and a link</a>
</div>. 
Run Code Online (Sandbox Code Playgroud)

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

我的代码示例在这里.你也可以从看这个中受益.

  • 一个非常非常好的答案.方式高于正常.你有很好的例子,你的"这是我的指令内容"使得它很容易在渲染版本中阅读.我不明白为什么Angular必须使用复杂的术语和概念,然后不包括像你这样容易理解的例子.+2 (18认同)
  • 好像他们已经改变了一点功能.至少在版本> = 1.2.9.模板中的内容不会添加到呈现的内容中.请参阅下面的@ TechExplorer的答案 (12认同)
  • @odiseo,你能不能把所有的Angular文档都写成简单易懂的英文,就像这样!+很多1. (4认同)

小智 75

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

具有ng-transclude的元素的内容不会被附加,而是被完全替换.

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

<div class="something">
    <button>some button</button>
    <a href="#">and a link</a>
</div>
Run Code Online (Sandbox Code Playgroud)

并不是

<div class="something"> This is my directive content
    <button>some button</button>
    <a href="#">and a link</a>
</div>
Run Code Online (Sandbox Code Playgroud)

谢谢.


小智 37

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

<div class="something"> This is my directive content <div class="something" ng-transclude></div></div>
Run Code Online (Sandbox Code Playgroud)

  • 这是其他答案中缺少的关键信息 (5认同)
  • 这个答案增加了很多信息.`ng-transclude`是充当占位符的属性,其中将放置被转换的内容. (3认同)

Sam*_*vic 5

来自维基:

"在计算机科学中,翻译是指通过引用将部分或全部电子文档纳入一个或多个其他文档."

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

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


Art*_*r S 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';
    }
  };
});
Run Code Online (Sandbox Code Playgroud)

index.html

<div ng-controller="Controller">
  <my-dialog>Check out the contents, {{name}}!</my-dialog>
</div>
Run Code Online (Sandbox Code Playgroud)

my-dialog.html

<div class="alert" ng-transclude></div>
Run Code Online (Sandbox Code Playgroud)

编译输出

<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>
Run Code Online (Sandbox Code Playgroud)

Transclude使具有此选项的指令的内容可以访问指令外部而不是内部的作用域。

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

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