Angularjs中指令模板函数有什么好处?

问题描述 投票:35回答:2

根据文档,template可以是一个函数,它接受两个参数,elementattributes,并返回表示模板的字符串值。它用HTML的内容替换当前元素。替换过程将所有属性和类从旧元素迁移到新元素。

compile函数处理转换模板DOM。它需要三个参数,elementattributestransclude函数。 transclude参数已被弃用。它返回一个link函数。

似乎templatecompile函数非常相似,可以实现相同的功能。 template函数定义模板,compile函数修改模板DOM。但是,它可以在template函数本身中完成。我不明白为什么要在template函数之外修改模板DOM。反之亦然,如果可以在compile函数中修改DOM,那么template函数的需求是什么?

javascript angularjs templates compilation directive
2个回答
50
投票

在将结果模板函数绑定到范围之前,可以使用编译函数来更改DOM。

请考虑以下示例:

<div my-directive></div>

您可以使用compile函数来更改模板DOM,如下所示:

app.directive('myDirective', function(){
  return {

    // Compile function acts on template DOM
    // This happens before it is bound to the scope, so that is why no scope
    // is injected
    compile: function(tElem, tAttrs){

      // This will change the markup before it is passed to the link function
      // and the "another-directive" directive will also be processed by Angular
      tElem.append('<div another-directive></div>');

      // Link function acts on instance, not on template and is passed the scope
      // to generate a dynamic view
      return function(scope, iElem, iAttrs){

        // When trying to add the same markup here, Angular will no longer
        // process the "another-directive" directive since the compilation is
        // already done and we're merely linking with the scope here
        iElem.append('<div another-directive></div>');
      }
    }
  }
});

因此,如果您的指令需要,您可以使用compile函数将模板DOM更改为您喜欢的任何内容。

在大多数情况下,tElemiElem将是相同的DOM元素,但有时如果指令克隆模板以删除多个副本(参见ngRepeat),它可能会有所不同。

在幕后,Angular使用双向渲染过程(编译+链接)来删除已编译的DOM片段的副本,以防止Angular为每个实例反复处理(=解析指令)相同的DOM如果该指令标记出多个克隆,从而产生更好的性能。

希望有所帮助!


在评论后添加:

templatecompile函数之间的区别:

Template function

{
    template: function(tElem, tAttrs){

        // Generate string content that will be used by the template
        // function to replace the innerHTML with or replace the
        // complete markup with in case of 'replace:true'
        return 'string to use as template';
    }
}

Compile function

{
    compile: function(tElem, tAttrs){

        // Manipulate DOM of the element yourself
        // and return linking function
        return linkFn(){};
    }
}

在调用compile函数之前调用模板函数。

虽然它们可以执行几乎相同的东西并共享相同的“签名”,但关键的区别在于模板函数的返回值将替换指令的内容(或replace: true时的完整指令标记),而编译函数是预期的以编程方式更改DOM并返回链接函数(或具有前后链接功能的对象)。

从这个意义上讲,如果只需要用字符串值替换内容,就可以将模板函数视为某种便利函数,而不必使用编译函数。

希望有所帮助!


6
投票

模板函数的最佳用途之一是有条件地生成模板。这允许您基于属性或任何其他条件自动创建模板。

我见过一些非常大的模板,它们使用ng-if来隐藏模板的各个部分。但是,不是将所有内容放入模板并使用可导致过度绑定的ng-if,而是可以从永远不会使用的模板函数的输出中删除DOM的各个部分。

假设您有一个包含子指令item-firstitem-second的指令。并且子指令永远不会改变外部指令的生命周期。您可以在调用编译函数之前调整模板的输出。

<my-item data-type="first"></my-item>
<my-item data-type="second"></my-item>

这些模板字符串将是:

<div>
  <item-first></item-first>
</div>

<div>
  <item-second></item-second>
</div>

我同意这是一个极端的简化,但我有一些非常复杂的指令,外部指令需要根据类型显示一个,大约20个不同的内部指令。我可以在外部指令上设置类型,并让模板函数使用正确的内部指令生成正确的模板,而不是使用transclude。

然后将正确格式化的模板字符串传递给编译函数等。

© www.soinside.com 2019 - 2024. All rights reserved.