自发现Ractivejs以来,我正在慢慢将我的应用程序转移到它上面。

在使用 Vanilla JavaScript构建html树结构来创建元素之前,请在完成后将其附加到页面上。我最近将它移到了Ractivejs上,它与一个小的树结构一起很好地工作,但是如果涉及到一个深度嵌套的对象,它将超出调用堆栈。

有没有一种方法可以将我在JavaScript中建立的元素附加到Ractivejs模板上并保留Ractivejs事件,还是有一种在不超出调用堆栈的情况下递归遍历大对象的方法?

例子

用JavaScript构建树的方式

var tree = {
  'childPages' : [{
    'name': 'first child',
    'childPages': []
  }, {
    'name': 'second child',
    'childPages': [{
       'name': 'second first sub child',
       'childPages': []
     }]
  }, {
    'name': 'third child',
    'childPages': [{
        'name': 'third first sub child',
        'childPages': [{
            'name': 'sub sub child',
            'childPages': []
         }]
     }]
  }]
};


function buildTree (tree) {
  var ul = document.createElement('ul');;
  for(var i =0; i < tree.childPages.length; i++){
    var li = document.createElement('li');
    li.innerText = tree.childPages[i].name;
    ul.appendChild(li);
    if (tree.childPages[i].childPages.length) {
       li.appendChild (buildTree(tree.childPages[i]));
    }
  }
  return ul;
}

document.body.appendChild(buildTree(tree));


如何在Ractivejs模板中构建树

var ractive = new Ractive({
  el : 'body',
  template: '#treeNode',
  data: {
'childPages' : [{
  'name': 'first child',
  'childPages': []
}, {
  'name': 'second child',
  'childPages': [{
    'name': 'second first sub child',
    'childPages': []
  }, {
    'name': 'second second sub child',
    'childPages': []
  }]
}, {
  'name': 'third child',
  'childPages': [{
    'name': 'third first sub child',
    'childPages': [{
      'name': 'sub sub child',
      'childPages': []
    }]
  }]
}]
  }
});
<script src="http://cdn.ractivejs.org/latest/ractive.js"></script>
<script id="treeNode" type="text/ractive">
  <ul>
    {{#each childPages}}
      <li>
         {{name}}
          {{#if childPages}}
           {{> treeNode}}
          {{/if}}
      </li>
     {{/each}}
  </ul>
</script>

最佳答案

通常,当您超出调用堆栈时,这是因为Ractive处理丢失的数据属性的方式-如果您有{{with foo}}{{bar}}{{/with}}foo.bar不存在,则{{bar}}引用将无法解析,因此它“进入上下文堆栈”,而是寻找bar

在大多数情况下,这确实很方便,但是在这种情况下可能会出现问题,因为如果树中的某个项目没有childPages属性,Ractive就会将栈上移到父级-这会将我们带入无限递归兔子洞。

有两种解决方案:

  • 确保树中的每个节点都具有childPages属性,即使它是一个空数组,也可以...
  • 使用受限引用。如果您使用this.childPages而不是childPages(或./childPages-这是等效的,则您可能会比较喜欢另一种),那么Ractive不会在当前上下文之外查找数据。这是一个示例,删除了所有空的childPages数组-没有this.,我们立即超过了调用堆栈,但是因为它在那里,所以我们完全安全。


  • var ractive = new Ractive({
      el : 'body',
      template: '#treeNode',
      data: {
    'childPages' : [{
      'name': 'first child'
    }, {
      'name': 'second child',
      'childPages': [{
        'name': 'second first sub child'
      }, {
        'name': 'second second sub child'
      }]
    }, {
      'name': 'third child',
      'childPages': [{
        'name': 'third first sub child',
        'childPages': [{
          'name': 'sub sub child'
        }]
      }]
    }]
      }
    });
    <script src="http://cdn.ractivejs.org/latest/ractive.js"></script>
    <script id="treeNode" type="text/ractive">
      <ul>
        {{#each this.childPages}}
          <li>
             {{name}}
              {{#if this.childPages}}
               {{> treeNode}}
              {{/if}}
          </li>
         {{/each}}
      </ul>
    </script>

    10-07 13:46