使用Chrome开发者工具中的时间轴,我使用这一小段代码通过 innerHTML 和 appendChild 方法录制事件:
<!DOCTYPE html>
<html>
<head>
<script>
function testInnerHTML(){
var wrap = document.getElementById('wrapper');
wrap.innerHTML = "test";
}
function testAppendChild(){
var wrap = document.getElementById('wrapper');
wrap.appendChild(document.createTextNode("test"));
}
</script>
</head>
<body>
<input type="button" value="innerHTML" onClick="testInnerHTML();"/>
<input type="button" value="appendChild" onClick="testAppendChild();"/>
<div id="wrapper"></div>
</body>
</html>
我可以看到:
在这个示例中,每个事件几乎不需要处理任何事情,并且似乎或多或少地并行发生,但是如果您使用大型html表执行此操作,您将看到重新计算的样式可能需要几秒钟,布局将在此之后发生。所以,如果我们能够避免它,那就更好了!
我在考虑使用带有文档片段的appendChild来避免innerHTML涉及的解析。但重新计算的风格使得节省的时间丢失了......
我使用的是Chrome版本23.0.1271.64 m
你知道为什么会这样吗? 我应该向我追加的节点添加一些内容,以帮助浏览器不触发重新计算样式事件吗?
PS:如果您想知道双重解析事件,可以参考Why does a click setting innerHTML trigger two parsing events on Chrome?
答案 0 :(得分:2)
在WebKit中,HTMLElement::setInnerHTML()
内部使用replaceChildrenWithFragment()
,其中包含以下特殊情况:
if (hasOneTextChild(containerNode.get()) && hasOneTextChild(fragment.get())) {
toText(containerNode->firstChild())->setData(toText(fragment->firstChild())->data(), ec);
return;
}
而不是ContainerNode::appendChild()
,它只是迭代地将节点插入容器并调度相应的事件(例如DOMNodeInserted
。)
我同意这可能会使用一些优化。