Compile and link functions inside angularjs directives

Giới thiệu

AngularJS directives thật sự là rất tuyệt vời với tính khả dụng cao khi được sử dụng ở trên view.Có rất nhiều bài viết đã hướng dẫn bạn cách thực hiện 1 directive của riêng bạn,tuy nhiên cũng có rất ít thông tin về sự hoạt động giữa các compile,link function.Trong bài viết này tôi sẽ giới thiệu với các bạn về sự hoạt động giữa các compile,link function, đầu tiên là về khaí niệm:

Compile: đi qua DOM and thu thập tất cả directives và tạo ra các liên kết với các template DOM. Kết quả là một linking function.

Link: link function tao ra liên kết của scope với DOM.

Cách thức xử lý các directives trong AngularJS

Khi trình duyệt render một trang, nó chủ yếu đọc đánh dấu HTML, tạo ra một DOM và đánh dấu các sự kiện khi DOM đã sẵn sàng.Khi thêm các đoạn mã trong AngularJS vào 1 trang thông qua các thẻ <script> </ script> AngularJS sẽ lắng nghe sự kiện đó ,nó sẽ truy cập vào DOM và tìm kiếm attribute ng-app được khai báo.Khi đc tìm thấy AngularJS bắt đầu sử dụng các DOM như là điểm khởi đầu. Vì vậy, nếu các thuộc tính ng-app được thiết lập trên các yếu tố html, AngularJS sẽ bắt đầu xử lý DOM bắt đầu từ phần tử html.Từ điểm khởi đầu, AngularJS đệ quy kiểm tra tất cả các phần tử con, tìm kiếm các directive đã được xác định trong ứng dụng AngularJS của bạn.Để làm đc như vậy ban có thể khai báo các Compile function, link function hoặc có thể tách link function thành pre-link và post-link.
Example:

<level-one>
    <level-two>
        <level-three>
            Hello {{name}}
        </level-three>
    </level-two>
</level-one>
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'));

Trên đây là 1 ví dụ rất đơn giản ,AngularJS sẽ biên dịch 3 directive và mỗi directive đều có compile ,pre-link và post-link cho riêng mình và tôi sử dụng console để ghi lại log cho tất cả các quá trình
Kết quả console log:

// 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

Ta có thể thấy chiều biên dịch của function compile và pre-link là cùng chiều ,tuần tự từ levelOne đến leverThree trong khi post-link lại chạy ngược lại từ levelThree đến levelOne

Và sau đây chính là luồng biên dịch của các directive:

cycle-2.png Compile

Chúng ta đã đc biết AngularJS chỉ có thể truy cập vào DOM khi mà DOM đã sẵn sàng, Vì vậy, khi AngularJS bắt đầu vượt qua các DOM, nó thâm nhập vào element <level-one> và biết được thông tin từ directive tương ứng của nó.
Một khi các chức năng biên dịch directive LevelOne đã chạy, AngularJS đệ quy đi qua sâu hơn vào các DOM và lặp đi lặp lại các bước biên dịch tương tự cho các <level-two> và <level-three>.
Post link

Sau AngularJS đi xuống DOM và đã chạy tất cả các chức năng compile, nó đi qua lại lên một lần nữa và chạy tất cả các chức năng post link liên quan.

DOM bây giờ là đi qua theo hướng ngược lại và do đó các chức năng sau liên kết được gọi theo thứ tự ngược. Vì vậy, trong khi thứ tự đảo ngược nhìn lạ một vài phút trước đây, bây giờ nó đang bắt đầu để làm cho cảm giác hoàn hảo.Thứ tự đảo ngược này đảm bảo cho các post-link function của tất cả các phần tử con đã chạy trước khi các function của các element cha . cycle.png