与许多textareas(但不是文本输入字段)反应缓慢

时间:2015-06-27 14:56:44

标签: reactjs

有很多textareas,我(无可否认大)的形式变得迟钝。

然而,使用文本输入字段,一切都很顺畅。

我创建了两个最小化的测试用例,一个包含textareas,另一个包含输入字段。单击切换按钮以显示/隐藏组以查看问题。至少使用Chrome,该组在textarea版本中切换的速度非常慢。

2500 textareas: http://jsbin.com/wudujusoji/edit?html,js,output

2500个文本输入字段: http://jsbin.com/rezudotojo/edit?html,js,output

我在这里做错了什么? textarea和文本输入字段版本的性能大致相同吗?

1 个答案:

答案 0 :(得分:8)

让我们使测试合理,并将shouldComponentUpdate添加到每个的Input组件中。

var Input = React.createClass({
  shouldComponentUpdate: function(nextProps){
    return nextProps.value !== this.props.value;
  },

console.time()如果你想测量一些数学或类似数据是好的,但要真正看到这里发生了什么,我们需要使用探查器。

我们将从<input>开始。我这样做了几次,对我来说总是大约14ms。

标记为“(程序)”的右侧灰色条是JS返回后浏览器自行完成的工作。这里需要大约17ms来准备渲染。在那之后闲置,除了绘画之外什么也没做。很酷,考虑到元素的数量,这还不错。

profiling the input example in chrome dev tools

textarea更有趣。这些中的反应平均值大约为30ms,考虑到它是开发构建,这很好。我不知道为什么chrome需要 500ms 来处理这些更改。

profiling the textarea example in chrome dev tools another profile of textarea yet another textarea profile

我认为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,但谁在数呢?