在编译阶段后创建新的DOM树,或者继续使用原始修改的DOM
does angular create new DOM tree after compile phase or continue working with original modified DOM?
例如,我有以下HTML:
<div dir-parent>
<div dir-child1></div>
</div>
在编译阶段,指令dirParent
将接收模板DOM元素,该元素内部有带有dirChild1
指令的div
。如果我不在dirParent
的编译函数中更改这个html
,那么就会为dirChild1
指令调用编译函数。但是,如果我在dirParent
的编译函数中删除了<div dir-child1="" some-child1-attr></div>
,那么angular将继续处理这个修改的DOM,该DOM不再具有带有dir-child1
指令的div,因此dir-child1
指令的编译函数永远不会执行。
我假设一旦angular执行完编译函数,它就会在编译函数期间从修改过的html
构建新的DOM。这个假设正确吗?这个修改过的DOM似乎被称为实例DOM元素,并且在pre-link
阶段可用,所以我假设这是angular构造实例元素DOM树的阶段。
我花了3个小时研究Angular的源代码(它是以难以阅读的方式编写的),找到了问题的答案。Angular不区分内部的模板元素和实例元素,它在开始编译时使用相同的树。以下是源代码的本质,它证明了:
var element = $("body");
compile(element)($rootScope);
function compile(DOMElementsTree) {
var compositeLinkFn = compileNodes(DOMElementsTree);
return function publicLinkFn(scope) {
var $linkNode = DOMElementsTree;
compositeLinkFn(scope, $linkNode);
return $linkNode;
}
}
function compileNodes(nodesList) {
var linkFns = [];
nodesList.forEach(function (node) {
var nodeLinkFn = applyDirectivesToNode(node);
var childNodes = nodesList.childNodes;
var childLinkFn = !!childNodes.length ? compileNodes(childNodes) : null;
if (nodeLinkFn || childLinkFn) {
linkFns.push(i, nodeLinkFn, childLinkFn);
}
});
return function compositeLinkFn(scope, nodeList) {
linkFns.forEach(function (linkFn) {
var nodeLinkFn = linkFn[1];
var childNodeLinkFn = linkFn[2];
if (nodeLinkFn) {
nodeLinkFn(childLinkFn, scope, nodeList);
} else if (childNodeLinkFn) {
childLinkFn(scope, nodeList)
}
});
}
}
function applyDirectivesToNode() {
// this is where compile functions of all directives on a node are executed
}
function nodeLinkFn() {
// here pre link and post link functions are executed
}
function childLinkFn() {
// here pre link and post link functions are executed
}
您可以看到,执行指令的compile
函数的applyDirectivesToNode
没有返回任何新的DOM节点,而是修改了通过引用接收的DOMElementsTree
,compositeLinkFn
继续使用此DOM实例。
最初,我的问题中有这样一段示例代码:
var $compile = ...; // injected into your code
var scope = ...;
var parent = ...; // DOM element where the compiled template can be appended
var html = '<div ng-bind="exp"></div>';
// Step 1: parse HTML into DOM element
var template = angular.element(html);
// Step 2: compile the template
var linkFn = $compile(template);
// Step 3: link the compiled template with the scope.
var element = linkFn(scope);
// Step 4: Append to DOM (optional)
parent.appendChild(element);
因此,在本摘录中,最后一步处理publicLinkFn
函数的结果,即我上面代码中的$linkNode
。
DOM
元素确实是在步骤1中创建的,但它只在浏览器内存中可用,而不会反映在实际的页面DOM中。
由于元素是在编译和链接后从Javascript(var html = ...
)创建的,因此需要使用append
将其放回页面,以便用户可以实际查看并与之交互
更新我不明白你到底在问什么,但我认为你不会在StackOverflow上找到答案。你需要的是一个论坛或更多关于AngularJS内部功能的讲座。我强烈建议您阅读这篇文章:http://www.jvandemo.com/the-nitty-gritty-of-compile-and-link-functions-inside-angularjs-directives/
Update2根据我的理解(根据上面引用的文章),Angular将首先从dir-parent
编译模板,然后使用相同的模板编译其子级。如果您在顶级编译阶段修改了该模板,例如删除了dir-child1
,那么实际上没有其他内容可编译,Angular将继续使用pre-link
,最后使用post-link
。
- 在单击任何位置时隐藏元素,而不检查每次DOM单击
- 是否有任何snippet或jQuery插件可以列出easylist.txt模式匹配的DOM中的所有元素
- 在不使用JQuery的情况下隐藏DOM中的选定元素
- 如何在DOM元素上按类型构建此函数
- Windows形成web浏览器控件和Javascript更改的DOM
- Datatables:通过DOM数据源中的名称引用列
- 在DOM中查找一个模式并替换它's的内容使用jquery
- DOM事件通过JSON转换为java
- 将DOM节点值与字符串Javascript进行比较
- delete在Object上效率低下,但在DOM Element's的数据属性,与null out相比
- 流星中DOM的繁殖
- DOM元素和angular元素之间的主要区别是什么
- 当带有渲染器的DOM元素不在屏幕顶部时,移动了场景的坐标
- 为什么继续;语句冻结浏览器
- 在编译阶段后创建新的DOM树,或者继续使用原始修改的DOM
- 继续加载.gif在操作 DOM 时进行动画处理
- 继续执行dom命令
- 继续尝试函数,直到所需的DOM元素加载
- jQuery/Javascript -如何在继续执行函数之前等待被操纵的DOM更新
- 在用户滚动时继续修改DOM