javascript - Angular 在编译阶段后会创建新的 DOM 树还是继续使用原始修改后的 DOM?

标签 javascript angularjs

例如,我有以下 HTML:

<div dir-parent>
    <div dir-child1></div>
</div>

编译阶段指令 dirParent将接收内部包含 div 的模板 DOM 元素与 dirChild1指示。如果我不改变这个html里面dirParent的编译函数,然后调用 dirChild1 的编译函数指示。但是,如果我删除 <div dir-child1="" some-child1-attr></div>里面dirParent的编译函数,然后 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 实例。

最初,我在提问 from here 中有这段示例代码:

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

关于javascript - Angular 在编译阶段后会创建新的 DOM 树还是继续使用原始修改后的 DOM?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29437692/

相关文章:

javascript - 如何使用 Protractor 从非 Angular 页面导航回另一个 Angular 页面

javascript - AngularJS - 将可选参数传递给模态

javascript - 在字符串的错误索引中插入的字符

javascript - 包含 HTML 标签但仅包含字符列表

javascript - 从 JavaScript 数组返回唯一键

html - 围绕图片angularjs对齐 block

angularjs - 使用 Angular - Flask 将请求方法更改为 OPTIONS/CORS

angularjs - 使用 ng-if 作为 ng-repeat 内部的开关?

javascript - 取消选择 <select> 中的顶部选项 - bootstrap multiselect

javascript - jQuery 在 DropDownList 中附加 UL 和 LI,反之亦然