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

标签 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 格式良好的位置。但我很乐意了解整个故事。

最佳答案

插值发生和不发生的地方有哪些规则?

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

The compilation is a process of walking the DOM tree and matching DOM elements to directives.

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 时,它仅在属性文本节点内搜索插值内容。

这些函数,addTextInterpolateDirectiveaddAttrInterpolateDirective“翻译”将插值表达式转换为$watch插值表达式的指令并更新 DOM 元素。

这在哪里记录?

编译阶段记录如下:http://docs.angularjs.org/guide/compiler

它每天都在进步,但仍然有一些深入的东西不清楚,直到你阅读源代码本身。我想有些事情太复杂了,如果不显示代码就无法解释。

导致这种情况的设计考虑或限制是什么?

我想有两个原因:

  • Angular 在 DOM 节点而不是字符串上运行,如果 Angular 需要插入属性或元素,那么它应该在 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?

关于html - 在什么情况下插值在 Angular 中是合法的,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21108732/

相关文章:

javascript - 选择器中的 CSS 类规范

javascript - 定义选项卡的 CSS 规则

angularjs - 为什么我的表单在 ng-app 指令中没有提交(angularjs)?

javascript - 达到 10 次摘要迭代,正在中止(作用域函数问题)

javascript - AngularJS:链接到使用 ng-repeat 的指令中的元素

javascript - 如何使用两个 CSS 文件设置一个 HTML 文件的样式?

javascript - 如何在 AngularJS 应用程序主体上动态设置溢出

html - 使两个元素适应智能手机屏幕

javascript - 将现有的backboneJS应用程序转换为angularJS应用程序的最佳方法是什么

javascript - 关于“AngularJS 与 Plupload 一起使用”的一些问题