我知道Angular的字符串插值通常对Handlebars风格{{ double curly braces }}
内的表达式进行操作,通过观察,我知道我可以在像
<span>{{ 'string literal expression ' }}</span>
<a href="{{ '/link/to/somewhere' }}">link</a>
而不是自己生成属性,即
<a {{ 'href="/link/to/elsewhere"' }}>link</a>
没有插值。
我对此感到好奇的是:插值在哪里发生和未发生的规则是什么,在哪里记录,以及导致这种情况的设计考虑因素或约束条件。
我想这是因为在Angular看到之前,浏览器将文档解析为HTML,因此结构由HTML决定,{{ stuff }}
必须出现在根据HTML格式良好的地方在插值发生之前。但我很高兴知道整个故事。
答案 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字符串上运行,这可能对性能不利。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?