2014-06-09 13 views
6

Tôi đã cố gắng tạo chỉ thị đệ quy của riêng mình với AngularJS, mà tự gọi là biến đổi một đối tượng trong chế độ xem với định dạng JSON đẹp. Đầu tiên, tôi đã sử dụng một ng-include để gọi một kịch bản lệnh với khuôn mẫu, với một ng-if bên trong nó xác minh nếu giá trị hiện tại là một đối tượng, nếu có, bản thân nó sẽ tự gọi.

Tôi luôn nghĩ rằng đây là một cách vô lý để làm điều đó, vì vậy tôi chuyển đổi trong một chỉ thị, đơn giản hơn nhiều.

Ít hơn ... Bởi vì tôi khám phá thế giới của các chỉ thị đệ quy và tìm thấy rất nhiều thứ, và thú vị nhất. Tôi thậm chí đã cho nó một đọc trong mã nguồn của Angular trong github (Tôi khuyên bạn nên đọc: https://github.com/angular/angular.js), với là một điều tốt.

Tôi đã tìm kiếm rất chăm chỉ, và tôi nghĩ tôi gần như tìm được awser sẽ trân trọng trái tim tôi! Bởi vì tôi học được rất nhiều điều mới và các bạn, sẽ giúp tôi.

Nhìn mã của tôi trong các liên kết dưới đây: https://github.com/Daymannovaes/htmljs/blob/master/js/directives/recursiveDataTemplateDirective.js

chỉ thị của tôi là: đệ quy-data-template = "data", nơi dữ liệu có một đối tượng. Chỉ thị này sẽ lặp qua khóa và giá trị của đối tượng này, và nếu giá trị là một đối tượng, sẽ làm điều này một lần nữa. Điều kiện được thực hiện với ng-if = "isObject (value)".

Ok, vấn đề đầu tiên của tôi là vòng lặp vô hạn. Tôi cần phải loại bỏ các nội dung trong giai đoạn biên dịch và sau đó bắt buộc biên dịch nội dung trong giai đoạn postLink. Câu hỏi của tôi: ** Tại sao biên dịch thủ công không rơi vào cùng một vấn đề của vòng lặp vô hạn? **

Tôi đang biên soạn cùng một nội dung, không có điều kiện nào được thực hiện (nếu if (! CompiledContent) bị xóa, vòng lặp vô hạn vẫn không xảy ra), sự khác biệt (tôi nghĩ) chỉ là chúng bị điên trong khác nhau nơi, nhưng tôi đã không thể tìm thấy trong internet một người nào đó awser câu hỏi của tôi!

Vì vậy, cảm ơn bạn! (nếu liên kết không làm việc, sau đây là các mã quan trọng):

compile: function(templateElement, templateAttributes) { 
      /* 
       in compile time, we need to remove the innerHTML of template(url) because of its recursive. 
       Because of its recusiveness, when the $compile start to read the DOM tree and find a 
       recursiveDataTemplate directive (even its not will be evaluated all time by link function 
       because the ng-if, whatever) its start the do all the process again. So, we need the .remove() 
      */ 
      var templateDirectiveContent = templateElement.contents().remove(); 
      var compiledContent; 

      return function($scope, linkElement, linkAttributes) { 

       /* 
        This verification avoid to compile the content to all siblings, because 
        when you compile the siblings, don't work (I don't know why, yet). 
        So, doing this we get only the top level link function (from each iteration) 
       */ 
       if(!compiledContent) { 
        compiledContent = $compile(templateDirectiveContent); 
       } 

       /* 
        Calling the link function passing the actual scope we get a clone object 
        wich contains the finish viewed object, the view itself, the DOM!! 
        Then, we attach the new dom in the element wich contains the directive 
       */ 
       compiledContent($scope, function(clone) { 
        linkElement.append(clone); 
       }); 
      }; 
     }, 
    } 
<ul> 
    <li data-ng-repeat="(key, value) in fields"> 
     <span data-ng-if="!isNumber(key)"> 
      {{key}}: 
     </span> 

     <span data-ng-if="isObject(value)" recursive-data-template="value"></span> 

     <span data-ng-if="!isObject(value)"> 
      {{value}} 
     </span> 

    </li> 
</ul> 
+0

Có một cái nhìn tại địa chỉ: https://github.com/dotJEM/angular-tree, cá nhân tôi không nghĩ rằng ý tưởng ban đầu của bạn của đệ quy ng-includes là như vậy một ý tưởng tồi, hãy nhớ rằng bạn có thể ngoại suy ý tưởng đó thành một tập hợp các chỉ thị, đó chính xác là những gì mà cây dotjem-góc cạnh thực hiện. Tôi nghĩ hợp lý để có một cặp chỉ thị, một chỉ thị xác định điểm bắt đầu, sau đó kết nối đệ quy, vì điều này sẽ cho phép bạn làm cây trong cây, mà không làm cho chúng xung đột với nhau. http://plnkr.co/edit/uaZVzUhPsDIsx93kzXSP?p=preview – Jens

+1

Đây là một câu hỏi rất hay và tôi rất tiếc là không có câu trả lời hay. – erilem

+0

Tôi đã đối mặt với cùng một vấn đề và giải quyết nó bằng cách sử dụng mẹo 'biên soạnContent'. Tôi cũng không thực sự hiểu tại sao, tôi muốn một số giải thích chính xác về tất cả các công cụ này. – floribon

Trả lời

1

Tôi tin rằng đoạn trích này từ official documentation có liên quan đến những gì bạn đang yêu cầu:

Lưu ý: Chức năng biên dịch không thể xử lý các chỉ thị đệ quy tự sử dụng trong t người thừa kế các mẫu hoặc các hàm biên dịch. Việc biên dịch các chỉ thị này dẫn đến một vòng lặp vô hạn và một lỗi tràn ngăn xếp. Điều này có thể tránh được bằng cách sử dụng thủ công $compile trong chức năng postLink để biên dịch mẫu của chỉ thị một cách bất hợp pháp thay vì dựa vào biên dịch mẫu tự động thông qua việc biên soạn template hoặc templateUrl hoặc biên dịch thủ công bên trong hàm biên dịch.

Và đi từ mã bạn đã cung cấp, bạn đã có vẻ như đã làm được những gì ghi chú này là gợi ý - đó là, tay biên dịch bên trong hàm (postLink) bạn đang trở về cho compile tài sản của bạn chỉ thị.

+0

Ok, tôi đã đọc nó. Nhưng đó là câu hỏi của tôi, tại sao biên dịch bên trong postLink không bắn một vòng lặp vô hạn quá? Tôi biên dịch toàn bộ templateUrl, chứa chính nó. – daymannovaes

+0

Thật thú vị khi biết rằng các tài liệu chính thức có một lưu ý về việc sử dụng $ compile trong hàm liên kết bài viết nhưng điều đó không trả lời câu hỏi thực tế từ daymannovaes. – erilem

0

Về lý do tại sao biên dịch trong postLink chứ không phải là giai đoạn compile tránh đệ quy vô hạn, đó là bởi vì tất cả các yếu tố của DOM được biên soạn thời tiết họ đang thực sự sử dụng hay không, trong khi link sẽ chỉ được kích hoạt khi các phần tử thực sự được liên kết: cho insteance nếu một cao hơn ng-if là giả, yếu tố con của nó sẽ không được preLinked, và do đó neithr postLinked ... Ít nhất là từ sự hiểu biết của tôi!

Tôi khuyên bạn nên bài viết này tốt: http://www.jvandemo.com/the-nitty-gritty-of-compile-and-link-functions-inside-angularjs-directives/

Các vấn đề liên quan