DOM节点创建与性能
DOM nodes creation vs perfomance
我有一个动态创建DOM节点以容纳来自服务器的GPS JSON数据的函数。随着节点数量的增加,浏览器的性能也随之提高降解。是否有任何方法重写/调整函数以提高性能?该函数的简化节点创建部分如下所示:
var table = document.createElement('table');
var tbody = document.createElement('tbody');
table.appendChild(tbody);
for(var i = 0; i<3000;i++){
var tr = document.createElement('tr');
for(var j=0;j<50;j++){
var td = document.createElement('td');
td.style.backgroundColor="#a"+j%10+'c';
tr.appendChild(td);
}
tbody.appendChild(tr);
}
您可能需要考虑使用某种可回收清单。
这样的列表通过删除位于视口外的DOM节点并在当前查看时重新创建它们来回收它们的元素。
长话短说-在任何给定时间,DOM中只存在当前查看的DOM节点
另一种技术是使用固定数量的单元格,然后根据用户滚动的位置填充数据
我敢说,没有其他的方法可以做到这一点-天真地创建150,000个DOM节点将完全摧毁您的滚动性能
一些例子- 一个纯JS的例子
- 一个建立在Polymer 之上的例子另一个在React 之上构建的例子
来源:http://elliottsprehn.com/personal/infinite-scroll.html
<!DOCTYPE html>
<style>
* { box-sizing: border-box; }
ul, li { list-style-type: none; padding: 0; margin: 0; }
h1 { font-size: 1.2em; }
#infinite-list {
width: 300px;
border: 1px solid #ccc;
margin: 1em;
position: relative;
}
#infinite-list .scroll-view {
overflow-y: scroll;
height: -webkit-calc(20em + 2px);
}
#infinite-list ul {
position: absolute;
top: 0;
width: -webkit-calc(100% - 16px);
}
#infinite-list li {
height: 2em;
line-height: 2em;
padding-left: 1em;
border-bottom: 1px solid #ccc;
}
#infinite-list li:last-child {
border-bottom: none;
}
#infinite-list .scroll-view .spacer {
height: -webkit-calc(2em * 20000);
}
</style>
<h1>Infinite Scrolling with a fixed number of DOM nodes</h1>
<div id="infinite-list">
<div class="scroll-view">
<ul>
<li><a href=""></a></li>
<li><a href=""></a></li>
<li><a href=""></a></li>
<li><a href=""></a></li>
<li><a href=""></a></li>
<li><a href=""></a></li>
<li><a href=""></a></li>
<li><a href=""></a></li>
<li><a href=""></a></li>
<li><a href=""></a></li>
</ul>
<div class="spacer"></div>
</div>
</div>
<script>
(function() {
function randRange(low, high) {
return Math.floor(Math.random() * (high - low)) + low;
}
function randPick(array) {
return array[randRange(0, array.length)];
}
// Randomly create a bunch of test data.
var tlds = ['.com', '.net', '.org', '.edu', '.co.uk'];
var domains = ['google', 'facebook', 'yahoo', 'apple', 'youtube', 'amazon'];
var data = [];
for (var i = 0; i < 20000; ++i) {
data.push(i + ' ' + randPick(domains) + randPick(tlds));
}
var list = document.querySelector('#infinite-list');
var listItems = document.querySelectorAll('#infinite-list li');
var scrollView = document.querySelector('#infinite-list .scroll-view');
var itemHeight = listItems[0].getBoundingClientRect().height;
var previous;
// Propagate scrolling with the mouse wheel.
list.onmousewheel = function(e) {
var delta = e.wheelDeltaY;
if (Math.abs(delta) < itemHeight) {
delta = itemHeight * (delta > 0 ? 1 : -1);
}
scrollView.scrollTop -= delta;
};
function update() {
var current = scrollView.scrollTop;
if (previous == current) {
webkitRequestAnimationFrame(update);
return;
}
previous = current;
var first = Math.ceil(current / itemHeight);
for (var i = 0; i < listItems.length; ++i) {
listItems[i].firstElementChild.textContent = data[first++];
}
webkitRequestAnimationFrame(update);
}
update();
})();
</script>
如果还没有,您可能希望隐藏正在其中创建节点的元素,并仅在循环结束时显示它。
。当你在它上面工作时,设置display:none;
,然后切换回display:block;
(或任何它是)。
更新:实际上,你甚至不需要隐藏它,尽管这是一种方法。更简洁的方法是,将表添加到文档中,直到完成所有节点的添加,然后才将其添加到主体中。
var table = document.createElement('table');
var tbody = document.createElement('tbody');
for(var i = 0; i<3000;i++){
var tr = document.createElement('tr');
for(var j=0;j<50;j++){
var td = document.createElement('td');
td.innerHTML = "#a"+j%10+'c';
td.style.backgroundColor="#a"+j%10+'c';
tr.appendChild(td);
}
tbody.appendChild(tr);
}
table.appendChild(tbody);
document.body.appendChild(table);
为单行创建一个模板,然后重复克隆它,这可能有助于获得浏览器的帮助:
var table = document.createElement('table');
var tbody = document.createElement('tbody');
table.appendChild(tbody);
// Make a template row once up front
var rowtemplate = document.createElement('tr');
for(var j=0;j<50;j++){
var td = document.createElement('td');
td.style.backgroundColor="#a"+j%10+'c';
tr.appendChild(td);
}
// Now clone it over and over instead of creating it piecemeal repeatedly
// Must pass true to ensure it clones whole tree, not just top level tr
for(var i = 0; i<3000;i++){
table.appendChild(rowtemplate.cloneNode(true));
}
显然,这取决于浏览器内部是否有帮助,但通常情况下,浏览器应该能够克隆现有的节点树,而不是从头手动创建每个元素。
相关文章:
- 创建一个类似链接的按钮,并通过Javascript函数打开一个新的弹出窗口
- 为effect Composer创建GodRays效果过程
- 从javascript创建一个列表
- 函数参数中的数据与指定变量之间的任何性能差异
- 提高JQuery的性能
- onkeyup无法动态创建多个文本区域
- 如何使用javascript从主svg对象动态创建svg视图框
- 如何访问声音管理器2创建的声音对象
- 它是否创建了许多不利于JavaScript性能的变量
- 从 JavaScript 创建 HTML 元素时的性能一致性是什么?
- 创建具有多个粒子大小的bufferGeometry.最佳性能
- 哪种创建特定大小画布的jQuery方法性能最好
- 使用生成的ID创建JavaScript集合的最具性能的方法
- 方法链与创建不同变量对性能的影响
- DOM节点创建与性能
- 共享自定义元素创建性能
- 使用requestAnimationFrame创建无限事件循环是否有性能成本?
- Sencha Touch 2.1:如何创建/销毁选项卡内容以提高性能
- 使用jQuery创建更深的嵌套节点和属性时,哪种方法性能更好
- 如何在pixi.js中创建具有良好性能的动画tile ?