有很多textareas,我(无可否认大)的形式变得迟钝。
然而,使用文本输入字段,一切都很顺畅。
我创建了两个最小化的测试用例,一个包含textareas,另一个包含输入字段。单击切换按钮以显示/隐藏组以查看问题。至少使用Chrome,该组在textarea版本中切换的速度非常慢。
2500 textareas: http://jsbin.com/wudujusoji/edit?html,js,output
2500个文本输入字段: http://jsbin.com/rezudotojo/edit?html,js,output
我在这里做错了什么? textarea和文本输入字段版本的性能大致相同吗?
答案 0 :(得分:8)
让我们使测试合理,并将shouldComponentUpdate添加到每个的Input组件中。
var Input = React.createClass({
shouldComponentUpdate: function(nextProps){
return nextProps.value !== this.props.value;
},
console.time()
如果你想测量一些数学或类似数据是好的,但要真正看到这里发生了什么,我们需要使用探查器。
我们将从<input>
开始。我这样做了几次,对我来说总是大约14ms。
标记为“(程序)”的右侧灰色条是JS返回后浏览器自行完成的工作。这里需要大约17ms来准备渲染。在那之后闲置,除了绘画之外什么也没做。很酷,考虑到元素的数量,这还不错。
textarea更有趣。这些中的反应平均值大约为30ms,考虑到它是开发构建,这很好。我不知道为什么chrome需要 500ms 来处理这些更改。
我认为React必须采取行动才能做到这一点,所以我(hackily)添加了MutationObserver。
var mObserver = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation, i) {
console.log('mutation ' + i + ': '
+ mutation.type
+ ', at '
+ mutation.target.parentNode.tagName
+ ' > '
+ mutation.target.tagName
+ '['
+ [].indexOf.call(mutation.target.parentNode.children, mutation.target)
+ ']'
+ ', on attribute ' + mutation.attributeName
+ ', from ' + mutation.oldValue
+ ' to ' + mutation.target.getAttribute(mutation.attributeName)
);
});
});
var moConfig = { attributes: true, childList: true, characterData: true, subtree: true };
React.render(React.createElement(Editor, null),
document.querySelector('.editor'),
function(){
var root = document.getElementById('root');
if (!root) throw new Error('no root');
mObserver.observe(root, moConfig);
}
);
点击按钮时会显示:
mutation 0: attributes, at DIV > DIV[0], on attribute class, from null to category
mutation 1: childList, at DIV > BUTTON[0], on attribute null, from null to null
所以是的...我非常确定更改div的类名和按钮的文本内容会导致它花费500ms更新。我的猜测是所有花在尝试布局textareas上。
与往常一样,“当我做X时渲染2,000个节点”的答案是不渲染2,000个节点; X(例如React)并不重要。
实际上,这里略超过5,000,但谁在数呢?