directive(指令里的)的compile,pre-link,post-link,link,transclude

The nitty-gritty of compile and link functions inside AngularJS directives  The nitty-gritty of compile and link functions inside AngularJS directives part 2: transclusion

[译]ng指令中的compile与link函数解析

AngularJS directives are amazing. They allow you to create highly semantic and reusable components(高度语义化和可复用的web组件). In a sense you could consider them as the ultimate precursor of web components.

There are many great articles and even books on how to write your own directives. In contrast, there is little information available(很少有涉及到compile和link之间的区别,更别提pre-link和post-link的区别) on the differences between the compile andlink function, let alone the pre-link and post-link function.

Most tutorials briefly mention the compile function as used mainly by AngularJS internally and then advise you to just use the link function as it should cover most use cases for custom directives.

That is very unfortunate because understanding the exact differences between those functions will greatly enhance your ability to understand the inner workings of AngularJS and to write better custom directives yourself.

清楚这些函数的区别,才能加强你的能力来理解Angualr内部的工作原理,才能写出更好的自定义指令。

So stay with me and by the end of this article you will know exactly what these functions are and when you should use them.

How directives are processed in AngularJS

Before we get started, let‘s first break down how AngularJS processes directives(理解Angular是怎样处理指令的).

When a browser renders a page, it essentially reads the HTML markup, creates a DOM and broadcasts an event when the DOM is ready.(浏览器“读”HTML标签,建立DOM书,广播“DOM Ready”事件)

When you include your AngularJS application code on a page using a <script></script> tag, AngularJS listens for that event and as soon as it hears it(只要Angular监听到“Dom Ready”事件,就开始遍历DOM结构), it starts traversing the DOM, looking for an ng-app attribute on one of the elements.

When such an element is found, AngularJS starts processing the DOM using that specific element as the starting point. So if the ng-app attribute is set on the html element, AngularJS will start processing the DOM starting at the html element.

From that starting point, AngularJS recursively investigates all child elements(从ng-app开始,Angular递归遍历所有的子元素), looking for patterns that correspond to directives that have been defined in your AngularJS application.

How AngularJS processes the element depends on(Angular如何处理元素取决于元素上面具体的定义的指令内容) the actual directive definition object. You can define a compile function, a link function or both. Or instead of a link function you can opt to define a pre-link function and a post-link function.

So what is difference between all those functions and why or when should you use them?

Stay with me...

The code

To explain the differences I will use some example code that is hopefully easy to understand.

Consider the following HTML markup:

<level-one>
    <level-two>
        <level-three>
            Hello {{name}}
        </level-three>
    </level-two>
</level-one>

and the following JavaScript:

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

function createDirective(name){
  return function(){
    return {
      restrict: ‘E‘,
      compile: function(tElem, tAttrs){
        console.log(name + ‘: compile‘);
        return {
          pre: function(scope, iElem, iAttrs){
            console.log(name + ‘: pre link‘);
          },
          post: function(scope, iElem, iAttrs){
            console.log(name + ‘: post link‘);
          }
        }
      }
    }
  }
}

app.directive(‘levelOne‘, createDirective(‘levelOne‘));
app.directive(‘levelTwo‘, createDirective(‘levelTwo‘));
app.directive(‘levelThree‘, createDirective(‘levelThree‘));

The goal is simple: let AngularJS process three nested directives where each directive has its own compilepre-link and post-link function that logs a line to the console so we can identify them.

That should allow us to take a first glimpse at what is happening behind the scenes when AngularJS processes the directives.

The output

Here is a screenshot of the output in the console:

Let‘s analyze

The first thing to pay attention to is the order of the function calls(注意函数调用的顺序):

// COMPILE PHASE
// levelOne:    compile function is called
// levelTwo:    compile function is called
// levelThree:  compile function is called

// PRE-LINK PHASE
// levelOne:    pre link function is called
// levelTwo:    pre link function is called
// levelThree:  pre link function is called

// POST-LINK PHASE (Notice the reverse order)
// levelThree:  post link function is called
// levelTwo:    post link function is called
// levelOne:    post link function is called

This clearly demonstrates how AngularJS first compiles all directives before it links them to their scope(Angular在将指令link到它们的作用域之前,先compile), and that the link phase is split up(link阶段分为两个阶段) in a pre-link and post-link phase.

Notice how the order of the compile and pre-link functions calls is identical but the order of the post-link function calls is reversed.(compile和pre-link是按顺序一一对应的,而post-link是相反的顺序)

So at this point we can already clearly identify the different phases, but what is the difference between the compile and pre-link function? They run in the same order, so why are they split up?

The DOM

To dig a bit deeper, let‘s update our JavaScript so it also outputs the element‘s DOM during each function call:

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

function createDirective(name){
  return function(){
    return {
      restrict: ‘E‘,
      compile: function(tElem, tAttrs){
        console.log(name + ‘: compile => ‘ + tElem.html());
        return {
          pre: function(scope, iElem, iAttrs){
            console.log(name + ‘: pre link => ‘ + iElem.html());
          },
          post: function(scope, iElem, iAttrs){
            console.log(name + ‘: post link => ‘ + iElem.html());
          }
        }
      }
    }
  }
}

app.directive(‘levelOne‘, createDirective(‘levelOne‘));
app.directive(‘levelTwo‘, createDirective(‘levelTwo‘));
app.directive(‘levelThree‘, createDirective(‘levelThree‘));

Notice the extra output in the console.log lines. Nothing else has changed and the original markup is still used.

This should provide us with more insights into the context of the functions.

Let‘s run the code again.

The output

Here is a screenshot of the output with the newly added code:

Observation

Printing the DOM reveals something very interesting: the DOM is different during thecompile and pre-link function(在compile和pre-link阶段,DOM是不一样的).

So what is happening here?

Compile

We already learned that AngularJS processes the DOM when it detects that the DOM is ready(当监测到DOM结构完成,Angular开始处理DOM).

So when AngularJS starts traversing the DOM, it bumps into the <level-one> element and knows from its directive definition that some action needs to be performed.

Because a compile function is defined in the levelOne directive definition object, it is called and the element‘s DOM is passed as an argument(元素作为一个参数,传进compile函数) to the function.

If you look closely you can see that, at this point, the DOM of the element is still the DOM that is initially created by the browser using the original HTML markup.

In AngularJS the original DOM is often referred to as the the template element(模版元素), hence also the reason I personally use tElem as the parameter name in the compile function, which stands for template element.

Once the compile function of the levelOne directive has run, AngularJS recursively traverses deeper into the DOM(往更深的DOM结构遍历) and repeats the same compilation step for the <level-two>and <level-three> elements.

Post-link

Before digging into the pre-link functions, let‘s first have a look at the post-linkfunctions.

If you create a directive that only has a link function(只有一个link函数,Angular会将其视作post-link函数), AngularJS treats the function as a post-link function. Hence the reason to discuss it here first.

After AngularJS travels down the DOM and has run all the compile functions, it traverses back up again(当Angular已经运行完所有的compile函数,会倒着遍历DOM并运行相关联的post-link函数) and runs all associated post-link functions.

The DOM is now traversed in the opposite direction and thus the post-link functions are called in reverse order(post-link是倒着的顺序). So while the reversed order looked strange a few minutes ago, it is now starting to make perfect sense.

This reverse order guarantees that the post-link functions of all child elements have run by the time(在父元素运行post-link函数之前,所有子元素上面面的post-link都已经运行过了) the post-link function of the parent element is run.

So when the post-link function of <level-one> is executed, we are guaranteed that thepost-link function of <level-two> and the post-link function of <level-three> have already run.

This is the exact reason(这是为什么建议将指令的逻辑放在post-link里面) why it is considered the safest and default place to add your directive logic.

But what about the element‘s DOM? Why is it different here?

Once AngularJS has called the compile function of a directive, it 1)  creates an instanceelement of the template element (often referred to as stamping out instances) and 2) provides a scope for the instance. The scope can be a new scope or an existing one, a child scope or an isolate scope, depending on the scope property of the corresponding directive definition object.

一旦Angular运行过compile函数,它就1) 生成模版元素的实例 2)提供该实例的scope

So by the time(在link函数运行之前,生成的实例和scope已经准备好了,在post-link阶段会作为参数传入post-link函数中) the linking occurs, the instance element and scope are already available and they are passed by AngularJS as arguments to the post-link function.

I personally always use iElem as parameter name in a link function to refer to the element instance.

So the post-link function (and pre-link function) receive the instance element(在post-link或pre-link函数,接受实例元素作为参数) as argument instead of the template element.

Hence the difference in the log output.

Pre-link

When writing a post-link function, you are guaranteed that the post-link functions of all child elements have already been executed.

In most cases that makes perfect sense and therefore it is the most often used place to write directive code.

However, AngularJS provides an additional hook, the pre-link function, where you can run code before any of the child element‘s post-link functions have run.

That is worth repeating:

The pre-link function is guaranteed to run on an element instance before any post-link function of its child elements has run.

So while it made perfect sense for post-link functions to be called in reverse order, it now makes perfect sense to call all pre-link functions in the original order again.

This also implies that a pre-link function of an element is run before any of its child elements pre-link functions as well, so for the sake of completeness:

pre-link function of an element is guaranteed to run before any pre-link orpost-link function of any of its child elements(pre-link函数在任何后代元素的pre-link或post-link函数之前运行).

Looking back

If we now look back at the original output, we can clearly recognize what is happening:

// HERE THE ELEMENTS ARE STILL THE ORIGINAL TEMPLATE ELEMENTS / 这里所有的元素还是模版元素

// COMPILE PHASE
// levelOne:    compile function is called on original DOM
// levelTwo:    compile function is called on original DOM
// levelThree:  compile function is called on original DOM

// AS OF HERE, THE ELEMENTS HAVE BEEN INSTANTIATED AND          // 在这里,所有的元素1)已经被实例化 2) 已经被绑定到一个scope上面
// ARE BOUND TO A SCOPE
// (E.G. NG-REPEAT WOULD HAVE MULTIPLE INSTANCES)

// PRE-LINK PHASE
// levelOne:    pre link function is called on element instance
// levelTwo:    pre link function is called on element instance
// levelThree:  pre link function is called on element instance

// POST-LINK PHASE (Notice the reverse order相反顺序)
// levelThree:  post link function is called on element instance
// levelTwo:    post link function is called on element instance
// levelOne:    post link function is called on element instance

Summary

In retrospect we can describe the different functions and their use cases as follows:

Compile function

Use the compile function to change the original DOM (template element) before(compile函数可以更改初始的DOM/模版元素,在Angular生成实例和绑定scope之前) AngularJS creates an instance of it and before a scope is created.

While there can be multiple element instances, there is only one(可以有许多个元素实例,却只有一个模版元素) template element. The ng-repeat directive is a perfect example of such a scenario. That makes the compile function the perfect place to make changes to the DOM that should be applied to all instances later on, because it will only be run once and thus greatly enhances performance if you are stamping out a lot of instances.

The template element and attributes are passed to the compile function as arguments, but no scope is available yet(模版元素,属性作为参数传入compile函数,scope此时还未生成):

/**
* Compile function
*
* @param tElem - template element
* @param tAttrs - attributes of the template element
*/
function(tElem, tAttrs){

    // ...

};

Pre-link function

Use the pre-link function to implement logic that runs when AngularJS has already compiled the child elements, but before any of the child element‘s post-link functions have been called.

The scope, instance element and instance attributes are passed to the pre-link function as arguments:

/**
* Pre-link function
*
* @param scope - scope associated with this istance
* @param iElem - instance element
* @param iAttrs - attributes of the instance element
*/
function(scope, iElem, iAttrs){

    // ...

};

Here you can see example code of official AngularJS directives that use a pre-link function.

Post-link function

Use the post-link function to execute logic, knowing that all child elements have been compiled and all pre-link and post-link functions of child elements have been executed.

This is the reason the post-link function is considered the safest and default place for your code.

The scope, instance element and instance attributes are passed to the post-link function as arguments:

/**
* Post-link function
*
* @param scope - scope associated with this istance
* @param iElem - instance element
* @param iAttrs - attributes of the instance element
*/
function(scope, iElem, iAttrs){

    // ...

};

Conclusion

By now you should hopefully have a clear understanding of the differences between thecompilepre-link and post-link function inside directives.

If not and you are serious about AngularJS development, I would highly recommend reading the article again until you have a firm grasp of how it works.

Understanding this important concept will make it easier to understand how the native AngularJS directives work and how you can optimize your own custom directives.

And if you are still in doubt and have additional questions, please feel free to leave a comment below.

----------------------------------------------------------------------

Transclusion.

A mysterious word I had never heard of before until I met AngularJS. I seriously thoughtMisko Hevery had invented the word himself, but it appeared to be an existing word:

In computer science, transclusion is the inclusion of a document or part of a document into another document by reference .

In AngularJS, transclusion is the mechanism that allows you to grab the content of the DOM element of your directive and include it anywhere in the directive‘s template.

So in the context of AngularJS, we could rephrase the original definition as:

In AngularJS, transclusion is the inclusion of the directive‘s DOM element content into the directive‘s template

In this article we investigate the influence of transclusion on the compilepre-link andpost-link functions inside an AngularJS directive.

The code

Because this article is an extension to part 1, we will use the same code we already discussed previously.

Consider the following HTML markup:

<level-one>
    <level-two>
        <level-three>
            Hello {{name}}
        </level-three>
    </level-two>
</level-one>

and the following JavaScript:

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

function createDirective(name){
  return function(){
    return {
      restrict: ‘E‘,
      compile: function(tElem, tAttrs){
        console.log(name + ‘: compile‘);
        return {
          pre: function(scope, iElem, iAttrs){
            console.log(name + ‘: pre link‘);
          },
          post: function(scope, iElem, iAttrs){
            console.log(name + ‘: post link‘);
          }
        }
      }
    }
  }
}

app.directive(‘levelOne‘, createDirective(‘levelOne‘));
app.directive(‘levelTwo‘, createDirective(‘levelTwo‘));
app.directive(‘levelThree‘, createDirective(‘levelThree‘));

providing the following console output:

which can be summarized as:

// COMPILE PHASE
// levelOne:    compile function is called
// levelTwo:    compile function is called
// levelThree:  compile function is called

// PRE-LINK PHASE
// levelOne:    pre link function is called
// levelTwo:    pre link function is called
// levelThree:  pre link function is called

// POST-LINK PHASE (Notice the reverse order)
// levelThree:  post link function is called
// levelTwo:    post link function is called
// levelOne:    post link function is called

and visualized as:

So let‘s add transclusion

Transclusion is enabled by adding a transclude property to the directive definition object(定义指令的对象):

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

function createDirective(name){
  return function(){
    return {
      restrict: ‘E‘,
      transclude: true,
      compile: function(tElem, tAttrs){
        console.log(name + ‘: compile‘);
        return {
          pre: function(scope, iElem, iAttrs){
            console.log(name + ‘: pre link‘);
          },
          post: function(scope, iElem, iAttrs){
            console.log(name + ‘: post link‘);
          }
        }
      }
    }
  }
}

app.directive(‘levelOne‘, createDirective(‘levelOne‘));
app.directive(‘levelTwo‘, createDirective(‘levelTwo‘));
app.directive(‘levelThree‘, createDirective(‘levelThree‘));

Adding transclude: true tells AngularJS to capture the content of the directive and make it available in the directive‘s template. The ng-transclude attribute can then be used inside the template to specify where(transclude告诉Angular,内容放在哪里) you want AngularJS to restore the content.

But before we add the ng-transclude attribute to template, let‘s have a look at what we get so far:

Interesting

First of all notice how the order of the compile functions is reversed:

// COMPILE PHASE (Notice the reverse order)
// levelThree:  compile function is called
// levelTwo:    compile function is called
// levelOne:    compile function is called

// PRE-LINK PHASE
// levelOne:    pre link function is called

// POST-LINK PHASE
// levelOne:    post link function is called

and even though we haven‘t transcluded the actual content yet using ng-transclude, allcompile functions are called:

So what is happening?

When AngularJS processes the levelOne directive, it sees that the transclude property is set to true in the definition object.

AngularJS now knows it first needs to process the content of the directive‘s element before it can make the processed content available inside the template.

To accomplish that, AngularJS first needs to process all child elements. So it starts travelling down the element‘s DOM.

When processing levelOne‘s content, it encounters the levelTwo directive and recursively repeats the same process until it has no more child elements to process.

As soon as the complete child DOM has been processed, AngularJS is ready to start applying the directives‘ compilepost-link and pre-link functions.

Since we haven‘t specified an ng-transclude attribute yet, the processed content is never put back into the DOM and we end up with a black hole where all child elements oflevelOne disappear.

This is rarely useful in real situations, but for the purpose of experimentation it demonstrates how all compile functions are called, even if the content is not effectively transcluded.

Now let‘s add ng-transclude

To get a complete picture of what‘s happening, let‘s add a template property to our directive definition object with a string value of <div ng-transclude></div> to tell AngularJS where to put the transcluded content:

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

function createDirective(name){
  return function(){
    return {
      restrict: ‘E‘,
      transclude: true,
      template: ‘<div ng-transclude></div>‘,
      compile: function(tElem, tAttrs){
        console.log(name + ‘: compile‘);
        return {
          pre: function(scope, iElem, iAttrs){
            console.log(name + ‘: pre link‘);
          },
          post: function(scope, iElem, iAttrs){
            console.log(name + ‘: post link‘);
          }
        }
      }
    }
  }
}

app.directive(‘levelOne‘, createDirective(‘levelOne‘));
app.directive(‘levelTwo‘, createDirective(‘levelTwo‘));
app.directive(‘levelThree‘, createDirective(‘levelThree‘));

and check the output again:

Let‘s analyze further

If we summarize the output:

// COMPILE PHASE (Notice the reverse order)
// levelThree:  compile function is called
// levelTwo:    compile function is called
// levelOne:    compile function is called

// PRE-LINK PHASE
// levelOne:    pre link function is called
// levelTwo:    pre link function is called
// levelThree:  pre link function is called

// POST-LINK PHASE (Notice the reverse order)
// levelThree:  post link function is called
// levelTwo:    post link function is called
// levelOne:    post link function is called

we can see that transclusion appears to reverse the order in which the compile functions are called.

Let‘s compare the difference visually:

Without transclusion

With transclusion

So why is transclusion reversing the order in which the compile functions are called?

If we look back at the initial output and how we defined transclusion earlier:

In AngularJS, transclusion is the inclusion of the directive‘s DOM element content into the directive‘s template

then we can quickly deduce that AngularJS needs to process the element‘s DOM content before it can make it available inside the template.

However, the element‘s child elements can also contain directives that apply transclusion themselves.

So AngularJS has to recursively traverse the DOM first to check if transclusion is enabled in child elements and then compile the DOM backwards to make sure all DOM changes correctly "bubble up" again to the top before the processed DOM is ready to be added to the original directive‘s template.

The initial black hole that we created before we included the ng-transclude attribute is a perfect example of this.

Finally, when compilation has finished, the pre-link and post-link functions are called in the same way as explained in part 1.

---------------上面的这篇看不太明白----

Understanding the transclude option of directive definition?

Consider a directive called myDirective in an element, and that element is enclosing some other content(带指令的元素包含有其它元素), let‘s say:

<div my-directive>
    <button>some button</button>
    <a href="#">and a link</a>
</div>

If myDirective is using a template, you‘ll see that the content of <div my-directive> will be replaced by your directive template. So having:

app.directive(‘myDirective‘, function(){
    return{
        template: ‘<div class="something"> This is my directive content</div>‘
    }
});

will result in this render(在浏览器中会渲染成这样,模版元素中的其它元素内容“没了”):

<div class="something"> This is my directive content</div>

Notice that the content of your original element <div my-directive> will be lost (or better said, replaced).

So, say good-bye to these buddies:

<button>some button</button>
<a href="#">and a link</a>

So, what if you want to keep your <button>... and <a href>... in the DOM? You‘ll need something called transclusion. The concept is pretty simple: Include the content from one place into another. So now your directive will look something like this:

app.directive(‘myDirective‘, function(){
    return{
        transclude: true,
        template: ‘<div class="something" ng-transclude> This is my directive content</div>‘
    }
});

This would render:

<div class="something"> This is my directive content
    <button>some button</button>
    <a href="#">and a link</a>
</div>.

In conclusion, you basically use transclude when you want to preserve the contents of an element when you‘re using a directive(当你想保留原先的内容时).

时间: 11-14

directive(指令里的)的compile,pre-link,post-link,link,transclude的相关文章

学习AngularJs:Directive指令用法(完整版)

这篇文章主要学习AngularJs:Directive指令用法,内容很全面,感兴趣的小伙伴们可以参考一下 本教程使用AngularJs版本:1.5.3 AngularJs GitHub: https://github.com/angular/angular.js/ AngularJs下载地址:https://angularjs.org/ 摘要:Directive(指令)笔者认为是AngularJ非常强大而有有用的功能之一.它就相当于为我们写了公共的自定义DOM元素或LASS属性或ATTR属性,并

angularjs学习之六(angularjs中directive指令的一般编程事件绑定 模板使用等)

angular js 中模板的使用,事件绑定以及指令与指令之间的交互 对应教学视频地址(需翻墙):angularjs教学视频 <!doctype html> <html ng-app="myapp"> <head> <meta charset="utf-8"/> </head> <body ng-controller="ShieldController"> <div&g

再谈 angularjs directive 指令

之前写过一篇了 http://www.cnblogs.com/keatkeat/p/3903673.html 但某些部分写的不太清楚,甚至有点错误,所以今天特地在这里再来谈谈. 这篇主要是说指令的隔离还有和controller的沟通. 指令的运行过程基本上我们可以简单的理解为 : template -> compile -> controller -> pre-link -> post-link 我们通常只是用到post link,但如果你的指令有嵌套,子层需要父层的一些值的话,可

angular源码分析 摘抄 王大鹏 博客 directive指令及系列

链接地址:http://www.cnblogs.com/web2-developer/p/angular-14.html $compile的功能:将一个html字符串或者一个DOM进行编译,返回一个链接函数.链接函数将作用域和模板链接在一起,编译的实质是遍历DOM树,匹配和处理DOM树上的指令. angularjs directive 实例 详解 http://blog.51yip.com/jsjquery/1607.html

AngularJS clone directive 指令复制

需求背景: directive模块化某表单信息,但表单信息可加入多条.此时就涉及到clone directive. 解决方式: 能够通过使用angularjs中$compile来进行clone directive.clone direcitve中常涉及到数据的绑定. 详细方法: tw.factory('DirectiveUtil', [function() { var DirectiveUtil = {}; DirectiveUtil.DirectiveBuilder = function(di

对Inode、Hard Link以及Soft Link的理解

一.EXT2/EXT3等文件系统的分区格式 Linux的文件系统从EXT2开始将文件的属性和文件的实际内容分开存储,文件的属性由inode存储,文件的内容由block存储. 系统在对磁盘进行分区格式化的时候,分区被以block大小为单位分割成多个块,block的大小可以为1KB.2KB或4KB:分区里的各个块被统一编号,然后被划分成各个区域,图1描述了一个分区的划分情况: 图1 分区划分情况 各区域解释: Boot Sector:启动扇区,利用这个多个分区的启动扇区可以实现多系统. Block

VC中LINK 2001 和 LINK 2009 的错误的解决

最近将两个开源C++项目编译成windows版本的时候遇到很多问题,关键是两个项目经过同事的修改之后,一个项目引用了另一个项目,两个项目的头文件中都有一些跨平台的关于数据类型,以及一些通用函数的定义,所以导致有冲突,编译的时候总是报错,报的最多的是“无法解析的外部符号”,经过近3天的折腾总算都通过了,这里是一些总结. 首先,关于VC中的lib,与linux下的静态库是不同的,在VC中编译动态库的时候会生成一个lib和一个对应的dll,使用者在使用的时候需要包含头文件以及连接到该lib,在发布最终

hard link与symbolic link区别

Linux下的文件组织方式是每个文件都占用一个inode,inode中存放有文件的权限信息.block信息等,可以理解为索引文件系统,通过inode索引到对应的block,即读取文件. hard link hard link其实就是多个文件连接到同一个inode,因此,这两个文件的信息几乎是一模一样的,hard link有以下特点: 1)你将两都中的任何一个删除,文件都不会被删除,你仍然可以通过另一个文件名来读取文件数据: 2)通过任一文件名来修改该文件数据都是一样的结果: 3)不同的文件系统文

AngularJS指令中的compile与link函数解析

AngularJS指令中的compile与link函数解析 通常大家在使用ng中的指令的时候,用的链接函数最多的是link属性,下面这篇文章将告诉大家complie,pre-link,post-link的用法与区别. 原文地址 angularjs里的指令非常神奇,允许你创建非常语义化以及高度重用的组件,可以理解为web components的先驱者. 网上已经有很多介绍怎么使用指令的文章以及相关书籍,相互比较的话,很少有介绍compile与link的区别,更别说pre-link与post-lin