【问题标题】:When to use Angular transclusion何时使用 Angular 嵌入
【发布时间】:2016-05-01 08:33:51
【问题描述】:

我正在阅读此页面中的一些示例:http://www.c-sharpcorner.com/UploadFile/17e8f6/transclusion-in-custom-angularjs-directive/

此页面提供了有用的示例。但是我想知道何时使用嵌入。原始示例:

<user-post user-name="{{user.Name}}" post-details="post" ng-repeat="post in user.Posts">
    <user-likes post-likes-count="{{post.Likes.length}}"></user-likes>
</user-post>

这是 userPost 指令的 HTML 模板:

<div class="panel panel-default panel-primary">
    <div class="panel-heading">
        <h5><strong>{{userName}}</strong></h5>
    </div>
    <div class="panel-body">
        <img ng-src="{{postDetails.Content}}" alt="Image" class="img-responsive" />
    </div>
    <div class="panel-footer" ng-transclude>
    </div>
</div>

但我可以重写它而不包含:

<div class="panel panel-default panel-primary">
    <div class="panel-heading">
        <h5><strong>{{userName}}</strong></h5>
    </div>
    <div class="panel-body">
        <img ng-src="{{postDetails.Content}}" alt="Image" class="img-responsive" />
    </div>
    <div class="panel-footer">
        <user-likes post-likes-count="{{likeCount}}"></user-likes>
    </div>
</div>

我想知道使用嵌入的最佳情况?

【问题讨论】:

  • 我将尝试解释嵌入,但在发布之前需要一段时间才能得到答案。

标签: angularjs transclusion


【解决方案1】:

要了解 Transclusion,以及何时/如何使用它,您必须了解一些关于您尝试表示的 DOM,以及角度指令如何在 DOM 中发挥作用。

具体来说,这与元素指令(restrict: 'E')有关。让我们将最基本的 HTML 用于我们可能采用的指令:

.directive('myDirective', function(){
  return {
    restrict: 'E',
    template: '<div></div>' +
              '<div></div>'
  };

用法:

<my-directive>Some Content</my-directive>

现在,这个问题是理解嵌入的关键

Some Content 最终去了哪里?

在这种情况下,Some Content 无处可去。当指令被注入 DOM 时,它被template 替换。模板不知道Some Content,也没有地方放,所以最终的DOM中也不会输出。

现在,添加嵌入,我们可以解决这个问题。

.directive('myDirective', function(){
  return {
    restrict: 'E',
    transclude: true,
    template: '<div></div>' +
              '<ng-transclude></ng-transclude>'
  };

现在,当 DOM 被编译时,Some Content 有一个地方可以去。嵌入允许将元素的内部内容放置在模板中,在 ng-transclude 指令所在的位置。

现在,嵌入可能会变得非常棘手,尤其是当您有一个指令嵌套在另一个指令的内部内容中时,但它可能非常强大。但是,如果您的指令在标记中的元素内没有内容,则不需要嵌入。有很多方法可以利用嵌入,但在它们的核心,它们最终都会回到这个概念。

【讨论】:

    【解决方案2】:

    您可以使用transclude 将一堆 html 注入您的指令中。创建指令的想法是让您拥有可在应用程序的各个部分中使用的可重用代码。嵌入允许您从模板进一步自定义指令的内容。

    按照您的示例,创建带有嵌入的 user-post 指令的想法是,您的用户帖子可能在您的应用程序的不同部分中没有完全相同的内容。

    如果您注意到 template 2,我可以添加一些额外的 HTML 以适应指令中的不同内容。

    模板 1:

    <user-post user-name="{{user.Name}}" post-details="post" ng-repeat="post in user.Posts">
        <user-likes post-likes-count="{{post.Likes.length}}"></user-likes>
    </user-post>
    

    模板 2:

    <user-post user-name="{{otherUser.Name}}" post-details="post" ng-repeat="post in otherUser.Posts">
        <user-likes post-likes-count="{{post.Likes.length}}"></user-likes>
    
        // this directive might loop through post.comments and display a list
        // of comments on the post.
        <user-comments post-comments="{{post.comments}}"></user-comments>
    
        <p>some other customize html</p>
    </user-post>
    

    现在我的应用程序中有 2 个用户帖子。一个有帖子和用户喜欢,另一个有用户喜欢和 cmets 的帖子。

    【讨论】:

      【解决方案3】:

      同一个 API 提供了两个独立的功能:常规嵌入元素嵌入

      对于常规嵌入,基本用例是:您希望将一些内容从一个模板包含或替换到另一个模板。使用常规嵌入有两种方法:ngTransclude 指令和嵌入函数。

      以下内容来自 Eric Greene,我认为这是对带有代码的正则嵌入的一个很好的解释,Understanding Transclusion.

      ngTransclude

      HTML 代码

      <div foo>
        Some Content Here
      </div>
      

      JavaScript 代码

      .directive("foo", function() {
        // returns the Directive Definition Object
        return {
          transclude: true,
          template: "<div>the template</div><div ng-transclude></div>"
        };
      })
      

      使用 ngTransclude 指令的结果是以下 HTML 输出。 HTML 代码

      <div foo>
        <div>the template</div>
        <div ng-transclude>Some Content Here</div>
      </div>
      

      转置函数

      第二种方法是使用transclude函数 在指令的 post-link 函数中提供。在下面的代码中, link 属性指向 post-link 函数。除非预链接 函数是专门提供的,所有引用一个链接函数 请参阅后链接功能。查看下面的代码以了解如何 使用 transclude 函数可以实现相同的目标:

      HTML 代码

      <div foo>
        Some Content Here
      </div>
      JavaScript Code
      .directive("foo", function() {
        return {
          template: "<div>the template</div>",
          transclude: true,
          link: function(scope, element, attrs, ctrl, transclude) {
            transclude(function(clone) {
              element.append(clone);
            });
          }
        };
      })
      

      transclude 函数被传递一个作为回调的参数 用于操作克隆元素的函数。在上面的代码中, 回调函数将接收克隆的内容作为参数,然后 该函数将克隆的内容添加到 DOM。的执行 的链接函数导致以下 HTML 输出:

      HTML 代码

      <div foo>
        <div>
            the template
            <div>Some Content Here</div>
        </div>
      </div>
      

      但是,对于元素嵌入,我想扩展他的答案,因为他的解释对于用例来说似乎令人困惑且不完整。在 Tero Parviainen 的博客“A Guide to Transclusion in Angularjs”中,他找到了元素嵌入的根源,主要是为了推迟 UI 某些部分的链接和附加。

      引用他的话:

      理解元素嵌入

      现在让我们将注意力转向您可以使用的另一种方法 嵌入:使用 transclude: 'element' 进行元素嵌入。

      元素嵌入的一个用例是当您想要推迟 为您的 UI 的某些部分进行链接和附件,直到某事 发生。由于元素嵌入本质上移除了部分 DOM 并让您可以使用嵌入将其放回原处 功能,您可以控制何时发生这种情况。

      例如,你 可能只想在一些之后链接和附加部分 DOM 父作用域上的条件变为真:我们在这里拥有的是 本质上是 ngIf 的简化版本。如果你看源码 ngIf 的代码,你现在应该能够理解它在做什么: 它使用元素嵌入来有条件地链接这部分 仅当条件表达式为真时才使用 DOM。这也解释了为什么 每当使用 ngIf 时,您都会在 DOM 树中看到 HTML cmets。他们是 通过元素嵌入插入。

      当我在页面上查看源代码时,我会在 Chrome 开发工具的“元素”选项卡中看到它,但不明白它的来源。我也看到了 ng-repeat。

      使用元素嵌入重复渲染。另一个用例 元素嵌入是如果你想链接和附加 DOM 的一部分 几次。

      例如,您可以有一个迭代的指令 在一个数组上,并为每个项目再次呈现 DOM 子树 数组,也使每个项目在范围内可用。这都可以 当我们将元素嵌入机制与克隆相结合时完成 attach 函数,因为这样我们就可以为 DOM 链接一个新的克隆 每个项目:这本质上是一个(非常)简化的版本 ng重复。内置的 ngRepeat 指令也使用元素 嵌入,虽然研究它的源代码并不像 使用 ngIf,因为您可以通过多种方式使用 ngRepeat 和所有 它包含的优化。但在它的核心,它只是一个 元素嵌入和克隆附加功能的应用。

      我觉得 Tero 关于按元素使用 Transclusion 的报道比我说的要好。

      【讨论】:

        猜你喜欢
        • 2019-04-24
        • 1970-01-01
        • 2016-11-10
        • 1970-01-01
        • 2022-08-08
        • 1970-01-01
        • 1970-01-01
        • 2019-05-03
        • 2015-10-04
        相关资源
        最近更新 更多