有人能简单解释一下吗?

文档看起来有点迟钝。我没有领会到什么时候该用一种而不是另一种的本质和大局。一个对比这两者的例子会很棒。


当前回答

这个问题太老了,我想做一个简短的总结,这可能会有所帮助:

编译为所有指令实例调用一次 编译的主要目的是返回/创建链接(可能是前/后)函数/对象。你也可以init指令实例间共享的东西。 在我看来,“链接”是这个功能的一个令人困惑的名字。我更喜欢“预渲染”。 link为每个指令实例调用,它的目的是准备在DOM中呈现指令。

其他回答

两个阶段:编译和链接

编译:

遍历DOM树寻找指令(元素/属性/类/注释)。指令的每次编译都可以修改它的模板,或者修改它还没有编译的内容。一旦一个指令被匹配,它就返回一个链接函数,这个函数在后面的阶段用于将元素链接在一起。在编译阶段的最后,我们有一个已编译指令及其对应的链接函数列表。

链接:

When an element is linked, the DOM tree is broken at its branch point in the DOM tree, and the contents are replaced by the compiled (and linked) instance of the template. The original displaced content is either discarded, or in the case of transclusion, re-linked back into the template. With transclusion, the two pieces are linked back together (kind of like a chain, with the template piece being in the middle). When the link function is called, the template has already been bound to a scope, and added as a child of the element. The link function is your opportunity to manipulate the DOM further and setup change listeners.

这个问题太老了,我想做一个简短的总结,这可能会有所帮助:

编译为所有指令实例调用一次 编译的主要目的是返回/创建链接(可能是前/后)函数/对象。你也可以init指令实例间共享的东西。 在我看来,“链接”是这个功能的一个令人困惑的名字。我更喜欢“预渲染”。 link为每个指令实例调用,它的目的是准备在DOM中呈现指令。

compile function - use for template DOM manipulation (i.e., manipulation of tElement = template element), hence manipulations that apply to all DOM clones of the template associated with the directive. link function - use for registering DOM listeners (i.e., $watch expressions on the instance scope) as well as instance DOM manipulation (i.e., manipulation of iElement = individual instance element). It is executed after the template has been cloned. E.g., inside an <li ng-repeat...>, the link function is executed after the <li> template (tElement) has been cloned (into an iElement) for that particular <li> element. A $watch() allows a directive to be notified of instance scope property changes (an instance scope is associated with each instance), which allows the directive to render an updated instance value to the DOM -- by copying content from the instance scope into the DOM.

注意,DOM转换可以在compile函数和/或link函数中完成。

大多数指令只需要一个链接函数,因为大多数指令只处理特定的DOM元素实例(及其实例作用域)。

One way to help determine which to use: consider that the compile function does not receive a scope argument. (I'm purposely ignoring the transclude linking function argument, which receives a transcluded scope -- this is rarely used.) So the compile function can't do anything you would want to do that requires an (instance) scope -- you can't $watch any model/instance scope properties, you can't manipulate the DOM using instance scope information, you can't call functions defined on the instance scope, etc.

但是,compile函数(像link函数一样)可以访问属性。因此,如果DOM操作不需要实例作用域,则可以使用compile函数。由于这些原因,这里有一个只使用compile函数的指令示例。它检查属性,但是不需要实例作用域来完成它的工作。

下面是一个同样只使用compile函数的指令示例。该指令只需要转换模板DOM,因此可以使用compile函数。

另一种帮助确定使用哪个的方法:如果在链接函数中不使用"element"参数,那么可能不需要链接函数。

因为大多数指令都有一个链接函数,所以我不打算提供任何示例——它们应该很容易找到。

注意,如果你需要一个编译函数和一个链接函数(或前和后链接函数),编译函数必须返回一个或多个链接函数,因为如果定义了'compile'属性,'link'属性将被忽略。

另请参阅

在定义指令时,'controller', 'link'和'compile'函数之间的区别 Dave Smith关于指令的精彩ng-conf 2104演讲(链接到视频中关于编译和链接的部分)

有点晚了。但是,为了方便将来的读者:

我偶然看到下面这个视频,它以一种非常棒的方式解释了Angular JS中的编译和链接:

https://www.youtube.com/watch?v=bjFqSyddCeA

复制/输入这里的所有内容不太令人愉快。我从视频中截取了几个截图,解释了编译和链接阶段的每个阶段:

第二张截图有点让人困惑。但是,如果我们按照步长编号,就很简单了。

第一个循环:首先在所有指令上执行“Compile”。 第二个循环:执行“Controller”和“Pre-Link”(只是一个接一个) 第三个循环:“Post-Link”以相反的顺序执行(从最里面开始)

下面是代码,它演示了上面的内容:

var app = angular.module('app', []);

app.controller('msg', ['$scope', function($scope){

}]);

app.directive('message', function($interpolate){
    return{

        compile: function(tElement, tAttributes){ 
            console.log(tAttributes.text + " -In compile..");
            return {

                pre: function(scope, iElement, iAttributes, controller){
                    console.log(iAttributes.text + " -In pre..");
                },

                post: function(scope, iElement, iAttributes, controller){
                    console.log(iAttributes.text + " -In Post..");
                }

            }
        },

        controller: function($scope, $element, $attrs){
            console.log($attrs.text + " -In controller..");
        },

    }
});
<body ng-app="app">
<div ng-controller="msg">
    <div message text="first">
        <div message text="..second">
            <div message text="....third">

            </div>              
        </div>  
    </div>
</div>

更新:

该视频的第二部分可以在这里找到:https://www.youtube.com/watch?v=1M3LZ1cu7rw,该视频以一个简单的例子解释了如何在Angular JS的编译和链接过程中修改DOM和处理事件。

这是Misko关于指令的演讲。http://youtu.be/WqmeI5fZcho?t=16m23s

Think of the compiler function as the thing that works on a template and the thing that is allowed to change the template itself by, for example, adding a class to it or anything like that. But it's the linking function that actually does the work of binding the two together because the linking function has access to the scope and it's the linking function that executes once for each instantiation of the particular template. So the only kind of things you can placed inside of the compile functions are things that are common across all of the instances.