# compile && link属性

## Angularjs 指令编译三阶段

1. 标准浏览器API转化

   将html转化成dom，所以⾃自定义的html标签必须符合html 的格式
2. Angular compile

   搜索匹配directive，按照priority排序，并执行directive上 的compile方法
3. Angular link

   执行directive上的link方法，进⾏行scope绑定及事件绑定

## 为什么编译的过程要分成compile和link?

简单的说就是为了解决性能问题，特别是那种model变化会影响dom结构变化的，而变化的结构还会有新的scope绑定及事件绑定，比如ng-repeat。

## compile和link的使用时机

* compile

  想在dom渲染前对它进行变形，并且不需要scope参数想在所有相同directive里共享某些方法，这时应该定义在compile里，性能会比较好返回值就是link的function，这时就是共同使用的时候
* link

  对特定的元素注册事件需要用到scope参数来实现dom元素的一些行为

## compile

* complie:function(tElement,tAttrs,transclude)
* complie函数用来对模版自身进行转换，仅仅在编译阶段运行一次
* complie中直接返回的函数是postLink，表示link参数需要执⾏行的函数，也可以返回一个对象⾥里⾯面包含preLink和postLink

## link

* link(scope,iElement,iAttrs,controller)
* link参数代表的是complie返回的postLink
* preLink 表示在编译阶段之后，指令连接到子元素之前运行
* postLink 表示会在所有子元素指令都连接之后才运⾏行
* link函数负责在模型和视图之间进行动态关联，对于每个指令的每个实例，link函数都会执行一次

**例子：**

index.html

```markup
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">

</head>
<body>
<div ng-app="myApp">

    <div ng-controller="firstController">
        <!--
            1. div 转换为dom结构
            2. 默认的优先级为0,哪个先定义哪个先使用

        -->
        <div ng-repeat="user in users" custom-tags="" custom-tags2>

        </div>

    </div>
</div>

<script src="//cdn.bootcss.com/angular.js/1.4.8/angular.js"></script>
<script type="text/javascript" src="app/index.js"></script>


</body>
</html>
```

app/index.js

```javascript
var i = 0;

var myApp = angular.module('myApp', [])

    .directive('customTags',function(){
        return {
            restrict : 'ECAM',
            template : '<div>{{user.name}}</div>',
            replace : true,
            compile:function(tElement,tAttrs,transclude){

                tElement.append(angular.element('<div>{{user.name}}{{user.count}}</div>'));

                // 编译阶段...
                console.log('customTags compile 编译阶段...');

                return {
                    // 表示在编译阶段之后，指令连接到子元素之前运行
                    pre:function preLink(scope,iElement,iAttrs,controller){
                        console.log('customTags preLink..')
                    },
                    // 表示在所有子元素指令都连接之后才运行
                    post:function postLink(scope,iElement,iAttrs,controller){

                        iElement.on('click',function(){
                            scope.$apply(function(){
                                scope.user.name = 'click after';
                                scope.user.count = ++i;
                                // 进行一次 脏检查
                            });
                        })

                        console.log('customTags all child directive link..')
                    }
                }
                // 可以直接返回 postLink
                // return postLink function(){
                    // console.log('compile return fun');
                //}
            },
            // 此link表示的就是 postLink
            link:function(){
//                iElement.on('click',function(){
//                    scope.$apply(function(){
//                        scope.user.name = 'click after';
//                        scope.user.count = ++i;
//                        // 进行一次 脏检查
//                    });
//                })
            }
        }
    })

    .directive('customTags2',function(){
        return {
            restrict : 'ECAM',
            replace : true,
            compile:function(){
                // 编译阶段...
                console.log('customTags2 compile 编译阶段...');

                return {
                    // 表示在编译阶段之后，指令连接到子元素之前运行
                    pre:function preLink(){
                        console.log('customTags2 preLink..')
                    },
                    // 表示在所有子元素指令都连接之后才运行
                    post:function postLink(){
                        console.log('customTags2 all child directive link..')
                    }
                }

            }
        }
    })


    .directive('customTags3',function(){

       // return postLink;
       return function(){

       }
    })

    .controller('firstController', ['$scope', function ($scope) {
        $scope.users = [
            {
                id:10,
                name:'张三'
            },
            {
                id:20,
                name:'李四'
            }
        ];
    }]);
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://xiaoxiami.gitbook.io/angularjs/zhi_ling/angular_zi_ding_yi_zhi_ling/compile_and-and_linkshu_xing.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
