Ractivejs中的递归部分超过调用堆栈

时间:2015-05-11 11:27:38

标签: javascript performance ractivejs

自从发现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));
&#13;
&#13;
&#13;

如何在Ractivejs模板中构建树

&#13;
&#13;
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': []
    }]
  }]
}]
  }
});
&#13;
<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>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:5)

通常当你超出调用堆栈时,由于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>