Angularjs中的指令模板函数有什么好处?
根据文档, template
可以是一个函数,它接受两个参数,一个element
和attributes
并返回一个表示模板的string值。 它用HTML的内容replace当前元素。 replace过程将所有属性和类从旧元素迁移到新元素。
compile
函数处理转换模板DOM。 它有三个参数,一个element
, attributes
和transclude
函数。 transclude
参数已被弃用。 它返回一个link
函数。
看起来template
和compile
function非常相似,可以达到同样的效果。 template
函数定义了一个模板, compile
函数修改了模板DOM。 但是,它可以在template
函数本身中完成。 我看不到为什么修改template
function以外的template
DOM。 反之亦然,如果可以在compile
函数中修改DOM,那么template
函数需要什么?
在生成的模板函数绑定到作用域之前,可以使用编译函数来更改DOM。
考虑下面的例子:
<div my-directive></div>
您可以使用编译function来更改模板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
function将模板DOM更改为任何你喜欢的东西。
在大多数情况下, tElem
和iElem
将是相同的DOM元素,但是有时候,如果一个指令克隆模板来删除多个副本(参见ngRepeat
),它可能会有所不同。
在幕后,Angular使用双向渲染过程(编译+链接)来压缩已编译的DOM片段的副本,以防止Angular必须对每个实例一遍又一遍地处理(=parsing指令)相同的DOM如果指令戳出多个克隆导致更好的性能。
希望有所帮助!
添加后评论:
template
和compile
函数的区别:
模板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'; } }
编译function
{ compile: function(tElem, tAttrs){ // Manipulate DOM of the element yourself // and return linking function return linkFn(){}; } }
在调用编译函数之前调用模板函数。
虽然他们可以执行几乎相同的东西并共享相同的“签名”,但关键的区别在于,模板函数的返回值将replace指令的内容(或者如果replace: true
,则为完整的指令标记),而编译函数预计将以编程方式更改DOM,并返回一个链接函数(或带有链接前后链接函数的对象)。
从这个意义上说,如果你只需要用string值replace内容,就可以将模板函数想象成某种方便的函数,而不必使用编译函数。
希望有所帮助!
模板函数的最佳用法之一是有条件地生成一个模板。 这使您可以根据属性自动创build模板。
我看到一些非常大的使用ng-if
的模板来隐藏模板的各个部分。 但相反,它将所有东西扔进模板,并使用ng-if
,这可能会导致过多的绑定,您可以从模板中删除部分DOM将永远不会被使用。
假设您有一个指令,将包含子指令item-first
或item-second
。 而且这个子命令不会改变外部命令的生效。 在调用编译函数之前,您可以调整模板。
<my-item data-type="first"></my-item> <my-item data-type="second"></my-item>
而这些模板string将是:
<div> <item-first></item-first> </div>
和
<div> <item-second></item-second> </div>
我同意这是一个极端简化,但我有一些非常复杂的指令,外部指令需要显示基于types的大约20个不同的内部指令之一。 而不是使用transclude,我可以在外部指令中设置types,并使模板函数使用正确的内部指令生成正确的模板。
然后将格式正确的模板string传递给编译函数等。