2012-12-30 16 views
6

Giả sử tôi có một cấu trúc dữ liệu như thế này:Recursion với doT.js

{ list: [ { 
     name: "1", 
     children: [{ 
       name: "1.1", 
       children: [] 
      }, 
      { 
       name: "1.2", 
       children: [{ 
        name: "1.2.1", 
        children: [] 
        } 
       ] 
      } 
     ] 
     }, 
     { 
     name: "2", 
     children: [{ 
       name: "2.1", 
       children: [{ 
        name: "2.1.1", 
        children: [] 
        },   
        { 
        name: "2.1.2", 
        children: [] 
        },    
        { 
        name: "2.1.3", 
        children: [] 
        } 
       ] 
      }, 
      { 
       name: "2.2", 
       children: [] 
      }, 
      { 
       name: "2.3", 
       children: [] 
      } 
     ] 
     }, 
     { 
     name: "3", 
     children: [{ 
       name: "3.1", 
       children: [] 
      } 
     ] 
     } 
    ] 
} 

Làm thế nào tôi sẽ đi về việc tạo ra một mẫu với doT.js rằng đệ quy sẽ đi qua các đối tượng và xây dựng danh sách lồng nhau?

Xây dựng chuỗi html trực tiếp trong JS với một hàm đệ quy là thẳng về phía trước đủ: (http://jsfiddle.net/fergal_doyle/WN8hZ/5/)

var html = ""; 
function buildList(a){ 

    if (a.length == 0){return}; 

    html += "<ul>"; 
    for (var i = 0; i < a.length; i++) 
    { 
     html += "<li>" + a[i].name; 
     buildList(a[i].children); 
     html += "</li>"; 
    } 
    html += "</ul>";    
} 
buildList(data.list); 

$("#out").html(html); 


Nhưng với doT.js đây là những gì tôi có và sau đó tôi stumped ! (http://jsfiddle.net/fergal_doyle/BTZpu/4/)

EDIT: tôi có thể làm điều đó bằng cách trộn trong một số JS với đánh giá (http://jsfiddle.net/fergal_doyle/he8AN/)

{{ function buildList(a) { }} 

    {{?a.length}} 
    <ul> 
     {{~a :v}} 
     <li> 
      {{=v.name}} 
      {{ buildList(v.children); }} 
     </li> 
     {{~}} 
    </ul> 
    {{?}} 

{{ } }} 

{{ buildList(it.list); }} 

Tôi đã cố gắng để đạt được nó bằng cách sử partials. Xác định một đoạn mã ul sau đó có đoạn mã đó gọi chính nó đi qua trong một mảng như một param, nhưng tôi nhận được một lỗi "quá nhiều đệ quy". Nếu có cách nào để làm việc dưới đây, thì nó có nhiều thứ hơn tôi nghĩ. (http://jsfiddle.net/fergal_doyle/qazGe/4/)

{{##def.ul:a: 
    <ul> 
    {{~a :value}} 
     <li>{{=value.name}}{{#def.ul:value.children}}</li> 
    {{~}} 
    </ul> 
#}} 

{{#def.ul:it.list}} 

Trả lời

3

Vấn đề là tại thời gian biên dịch. doT.js dường như không xử lý đệ quy trong partials. Mã đệ quy {{#def.ul:value.children}} làm cho thư viện doT.js vô hạn giải quyết/thay thế bằng nội dung của hàm của bạn. Một cách để giải quyết vấn đề này là sử dụng arguments.callee để tham khảo một phần của bạn trong phần của bạn. Dưới đây là một ngã ba của bạn FIDDLE

{{##def.ul:a: 
    <ul> 
    {{~a :value}} 
    <li>{{=value.name}}{{=arguments.callee(value.children)}}</li> 
    {{~}} 
    </ul> 
#}} 

{{#def.ul:it}} 

Tác giả (s) của thư viện có thể thực hiện những ý tưởng tương tự trong thư viện của mình trong thời trang sau (chưa được kiểm tra):

function resolveDefs(c, block, def) { 
    return ((typeof block === 'string') ? block : block.toString()) 
    .replace(c.define || skip, function(m, code, assign, value) { 
     if (code.indexOf('def.') === 0) { 
      code = code.substring(4); 
     } 
     if (!(code in def)) { 

      // HANDLE RECURSION START 
      value = value.replace(c.use || skip, function(m, recursiveCode) { 
       if (c.useParams) return recursiveCode.replace(c.useParams, function(m, s, d, param) { 
        if(d == code) { 
         var ret = s + "{{=arguments.callee("; 
         if(param) 
          ret += param; 
         return ret + ")}}"; 
        } 
       }); 

      }) 
      // HANDLE RECURSION END 

      if (assign === ':') { 
... 
Các vấn đề liên quan