我正在对Angular和React进行比较,并决定尝试性能测试,看看大型(ish)列表在两个框架中的呈现速度有多快。
当我完成使用基本货币格式化的React原型时,在我的快速笔记本电脑上渲染需要大约2秒钟。使用Angular它几乎不会引人注意 - 只有当我切换到我的手机时才会有明显的滞后。
这是非常令人惊讶的,因为有人告诉我React应该从Angular中击败裤子以获得性能,但在这种情况下看起来恰恰相反。
我将原型提炼为一个非常简单的应用程序,试图找出问题所在:https://github.com/pselden/react-render-test
在这个示例中,更改语言后渲染这个简单的列表需要近200毫秒,而我几乎没有做任何事情。
我在这里做错了吗?
/** @jsx React.DOM */
'use strict';
var React = require('react'),
Numbers = require('./Numbers');
var numbers = []
for(var i = 0; i < 2000; ++i){
numbers.push(i);
}
var App = React.createClass({
getInitialState: function() {
return { locale: 'en-US' };
},
_onChangeLocale: function(event) {
this.setState({locale: event.target.value});
},
render: function() {
var currentLocale = this.state.locale;
return (
<div>
<select
onChange={this._onChangeLocale}>
<option value="en-US">English</option>
<option value="fr-FR">French</option>
</select>
<Numbers numbers={numbers} locales={[currentLocale]} />
</div>
);
}
});
module.exports = App;
/** @jsx React.DOM */
'use strict';
var React = require('react'),
ReactIntlMixin = require('react-intl');
var Numbers = React.createClass({
mixins: [ReactIntlMixin],
getInitialState: function() {
return {
numbers: this.props.numbers
};
},
render: function() {
var self = this;
var list = this.state.numbers.map(function(number){
return <li key={number}>{number} - {self.formatNumber(number, {style: 'currency', currency: 'USD'})}</li>
});
return <ul>{list}</ul>;
}
});
module.exports = Numbers;
PS:添加了角度版本:https://github.com/pselden/angular-render-test
编辑:我用react-intl打开了一个问题,我们进行了调查,发现使用https://github.com/yahoo/react-intl/issues/27时没有 的开销很大 - 这只是React本身在这里比较慢。答案 0 :(得分:44)
这绝对是一个有趣的测试案例。
如果您查看时间轴,您可以看到Angular已经完成了仅仅20ms的处理变更事件。剩余的时间用于布局和重新绘制。
React(使用生产版本,您的repo默认使用dev)大约需要59ms。同样,剩下的时间用于布局和重新绘制。
如果你看一下CPU火焰图,你可以看到Angular似乎做了很多工作。
角:
阵营:
React以shouldComponentUpdate
的形式提供了一个非常好的优化钩子,当成千上万的组件的单个实例应该更新而其他组件应该保持不变时,这个钩子特别有用;它是我在this demo中使用的一种技术(在隐身窗口中试用;我发现一些Chrome扩展程序使布局/重绘时间更高 - 对我而言,添加/删除单个元素一次list是1000 long需要~13ms,更改元素的大小/颜色需要~1ms)。但是,当每个元素都需要更新时,它没有用。
我的猜测是Angular在更改表格中的大部分或全部元素方面会更快,而React在使用shouldComponentUpdate
时非常精通更新选择条目。
答案 1 :(得分:3)
我很惊讶没人提到PureRenderMixin。它实现了shouldComponentUpdate
,因此您不必担心它。
另外,我想知道React Performance Tools是否会出现一些有用的东西?
看到this talk from Ryan Florence后,我很惊讶听到Angular比React快。
答案 2 :(得分:2)
我们试图分析我们框架的一些属性,当然,这不是整个列表。下面是我们认为比较属性的综合和重要的表格。
让我们获取更多细节:
虽然Angular vs React的差异很多,但它们可以做同样的事情,即构建客户端接口。两者都有自己的位置。对于那些喜欢Web开发的人来说,最重要的是创新的AngularJS HTML方法。
AngularJS确实是一个完整的框架而不仅仅是一个库,就像ReactJS一样,但ReactJS通过实现虚拟DOM具有比AngularJS更好的性能。我们认为,您应该在以下情况下使用AngularJS:
然而,双向数据绑定经常被吹捧使用AngularJS,但由于它是通过系列摘要实现的,因此为某些函数和表达式添加过多的复杂性会导致应用程序performance的恶化
答案 3 :(得分:1)
在这种特殊情况下,您需要注意状态逐渐减少,DOM更新也是如此。你想要做的是创建一个Price组件,它将语言环境存储在自己的状态,并接收一个信号(即通道或通量)来改变语言环境,而不是一直向下发送语言环境。我们的想法是,您不需要更新整个Numbers组件,只需更新内部价格。该组件可能如下所示:
var Price = React.createClass({
mixins: [ReactIntlMixin],
componentDidMount: function() {
subscribeToLocal(this.onLocaleChange);
},
onLocaleChange: function(newLocales) {
this.setState({locales: newLocales});
},
render: function() {
return <span>this.formatNumber(this.props.number, this.state.locales, {style: 'currency', currency: 'USD'})</span>
}
});
答案 4 :(得分:1)
In React component, once you call setState, it will trigger the render function immediately. React will mark this component as dirty, and will re-render all the children element inside this component.
It will not render the whole Native DOM elements because of the Virtual DOM, thus it will still create new instances of its children ReactElements, which can lead to extra Javascript memory cost.
To avoid this issue, you need shouldComponentUpdate function which implemented in Component Class. it will executed before Render method. If you find the there is nothing changed right now, for instance in your example, you change the state.locale. You can definitely consider this component need no update. so just return false to prevent the render call.
This is a base solution to solve React performance issues. Try to add "shoudlComponentUpdate" in your Numbers Component to avoid tons of
答案 5 :(得分:1)
这是一个例子,其中所有正在改变的是一个数据输出。当所有正在改变的是绑定数据的显示时,Angular的双向数据绑定简单地提供更快的重新渲染并非不可能。
React不承诺在任何情况下其渲染都比任何其他框架更快。它提供的功能是能够以非常有效的方式处理〜任意复杂的DOM更新,并提供各种生命周期方法(例如componentWillReceiveProps,componentDidUpdate,以及上述的shouldComponentUpdate),以便您可以触发这些事件的回调和控制如何以及是否应该发生。在这里,优化很少,因为您所做的只是更改2,000个文本显示。
编辑:为了澄清,React在执行更复杂的DOM操作时非常有用,因为它的虚拟DOM算法允许它选择更新DOM所需的最小DOM操作集。当需要发生的所有事情都是2000个文本更改的实例时,仍然需要做很多工作。