我知道做多次dom操作很糟糕,因为它会强制多次重绘。
即:
$('body').append('<div />')
.append('<div />')
.append('<div />')
.append('<div />');
相反,更好的做法显然是:
$('body').append('<div><div></div><div></div><div></div><div></div></div>');
但我对虚拟操作感到好奇
即:
$('<div />').append('<div />')
.append('<div />')
.append('<div />')
.append('<div />')
.appendTo('body');
它仍然很糟糕,显然会多次调用函数会产生一些开销,但是会有任何严重的性能命中吗?
<小时/> 我要问的原因是:
var divs = [
{text: 'First', id: 'div_1', style: 'background-color: #f00;'},
{text: 'Second', id: 'div_2', style: 'background-color: #0f0;'},
{text: 'Third', id: 'div_3', style: 'background-color: #00f;'},
{text: 'Fourth', id: 'div_4', style: 'background-color: #f00;'},
{text: 'Fifth', id: 'div_5', style: 'background-color: #0f0;'},
{text: 'Sixth', id: 'div_6', style: 'background-color: #00f;'}
];
var element = $('<div />');
$.each(divs, function(i,o){
element.append($('<div />', o));
});
$('body').append(element);
想象一下,divs数组来自描述表单的数据库表(好吧,我在示例中使用div,但可以很容易地用输入替换)或类似的东西。
或使用“推荐”版本:
var divs = [
{text: 'First', id: 'div_1', style: 'background-color: #f00;'},
{text: 'Second', id: 'div_2', style: 'background-color: #0f0;'},
{text: 'Third', id: 'div_3', style: 'background-color: #00f;'},
{text: 'Fourth', id: 'div_4', style: 'background-color: #f00;'},
{text: 'Fifth', id: 'div_5', style: 'background-color: #0f0;'},
{text: 'Sixth', id: 'div_6', style: 'background-color: #00f;'}
];
var element = '<div>';
$.each(divs, function(i,o){
element += '<div ';
$.each(o, function(k,v){
if(k != 'text'){
element += k+'="'+v+'" ';
}
});
element += '>'+o.text+'</div>';
});
element += '</div>';
$('body').append(element);
答案 0 :(得分:10)
首先,虽然很好地阅读这样的潜在性能命中,但您应该始终先测量一下,看看是否有问题。
如果您无法察觉问题,请编写最易读的代码。
如果您能感知到问题,请进行测量,更改和测量。
说完这一切后,您发布的最后一个示例涉及尚未写入DOM的元素,因此在appendTo
将元素添加到DOM之前不会重新绘制。
如果能够捕捉到第二个和第三个例子之间的速度差异,我会非常惊讶 - 如果你能看到它们之间有任何重大差异,我会感到非常惊讶。
答案 1 :(得分:1)
如果您在添加节点时真的担心性能,则需要使用documentfragments。这些将允许您将元素附加到dom而不重新绘制。 John Resign在此主题上有一个excellent article。他指出,性能提升了200-300%。我在我的一个应用程序中实现了文档碎片,并可以确认他的声明。
答案 2 :(得分:1)
在运行时生成好的旧标记会发生什么? 说真的,发生了什么?
我同意@ Sohnee关于可读性重要性的观点,但DOM操作是浏览器可以执行的一些最昂贵的操作。保持一串标记的选项可以完全可读,并提供超出可忽略的用户体验改善。
在this jsperf中,我们在运行时创建了一个10x100表 - 这是一个完全合理的(而不是迄今为止最复杂的情况)数据分页。在运行最新版Chrome的四核机器上,直接DOM操作脚本需要60ms才能完成,而标记缓存则需要3ms。
这对我的设置来说是一个难以区分的差异,但是那些坐在公司防火墙后面的数字拙劣的人仍然被迫使用过时的IE版本呢?如果所需的DOM操作更重,具有属性操作和积极强制re-paints/re-flows怎么办?
我要说的是,如果你想要优化一些javascript,这不是一个糟糕的起点。
答案 3 :(得分:0)
我认为如果你开始达到这种代码是性能瓶颈的程度,你应该使用模板而不是DOM操作。
但是,是的,使用文档片段方法(在连接到DOM之前将所有节点放入分离节点)在大多数情况下会更快,几乎从不慢。