在什么情况下,Angular中的插值合法,为什么?

时间:2014-01-14 08:18:25

标签: html angularjs

我知道Angular的字符串插值通常对Handlebars风格{{ double curly braces }}内的表达式进行操作,通过观察,我知道我可以在像

这样的上下文中使用它
  • HTML标记之外的文字:<span>{{ 'string literal expression ' }}</span>
  • HTML标记内的属性值:<a href="{{ '/link/to/somewhere' }}">link</a>

而不是自己生成属性,即

  • <a {{ 'href="/link/to/elsewhere"' }}>link</a>

没有插值。

我对此感到好奇的是:插值在哪里发生和未发生的规则是什么,在哪里记录,以及导致这种情况的设计考虑因素或约束条件。

我想这是因为在Angular看到之前,浏览器将文档解析为HTML,因此结构由HTML决定,{{ stuff }}必须出现在根据HTML格式良好的地方在插值发生之前。但我很高兴知道整个故事。

1 个答案:

答案 0 :(得分:4)

插值的作用和不发生的规则是什么?

Angular.js使用$ compile服务来编译一块DOM。 The docs说:

  

编译是一个遍历DOM树并将DOM元素与指令匹配的过程。

compile.js的源代码中有一个函数collectDirectives,我将其修剪为仅显示相关代码:

function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) {
  var nodeType = node.nodeType;
  // ....
  switch(nodeType) {
    case 1: /* Element */

      // ....

      // iterate over the attributes
      for (var attr, name, nName, ngAttrName, value, nAttrs = node.attributes,
               j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {          
        // ....
          addAttrInterpolateDirective(node, directives, value, nName);
        // ....
      }

      // ....
      break;
    case 3: /* Text Node */
      addTextInterpolateDirective(directives, node.nodeValue);
      break;
    case 8: /* Comment */
      // ....
      break;
  }

  directives.sort(byPriority);
  return directives;
}

如您所见,$ compile在迭代一块DOM时仅在属性文本节点内搜索插值内容。

这些函数,addTextInterpolateDirective addAttrInterpolateDirective 将“插值”插入到$ watch插值表达式并更新DOM元素的指令中。

哪里有记录?

编译阶段记录在此处:http://docs.angularjs.org/guide/compiler

它每天都在变得越来越好,但在您阅读源代码本身之前,仍然有一些深入的内容尚不清楚。我猜有些东西太过于无法解释而没有显示代码。

导致这种情况的设计考虑因素或约束是什么?

我猜有两个原因:

  • Angular operates on DOM nodes rather than strings,如果需要插入属性或元素的角度,那么它应该在 html字符串上运行,这可能对性能不利。
  • 这类事情没有重大用例。

如果您仍想插入所有内容,请在指令中执行此类魔术:

example

app.directive('myAnchor',function(){
  return {
    restrict: "E",
    transclude: true,
    link: function(scope,element,attrs,ctrl,$transclude) {

      attrs.$observe('interpolate', function(val){   
        var e = angular.element("<a " + val + "></a>");
        $transclude(scope,function(clone){
           e.append(clone);
        });
        element.replaceWith(e);
      });
    }
  };
});

请务必阅读:

What is the difference between the $parse, $interpolate and $compile services?