如今关于 React 最新 v16 版本新特性的宣传、讲解已经“铺天盖地”了。你最喜欢哪个 new feature?
截至目前,组件构建方式已经琳琅满目。那么,你考虑过他们的性能对比吗?这篇文章,聚焦其中一个小细节,进行对比,望读者参考的同时,期待大神斧正。前端
先上结论:在咱们的测试当中,使用 React.PureComponent 可以提高 30% JavaScript 执行效率。测试场景是反复操做数组,这个“反复操做”有所讲究,咱们计划持续不断地改变数组的某一项(而不是整个数组的大范围变更)。react
线上参考地址: 请点击这里git
那么这样的场景,做为开发者有必要研究吗?若是你的应用并不涉及到高频率的更新数组某几项,那么大可没必要在乎这些性能的微妙差异。可是若是存在一些“实时更新”的场景,好比:github
那么就须要进行考虑。咱们定义:changedItems.length / array.length 比例越小,本文所涉及的性能优化越应该实施,即越有必要使用 React.PureComponent。后端
在使用 React 开发时,相信不少开发者在搭配函数式的状态管理框架 Redux 使用。Redux reducers 做为纯函数的同时,也要保证 state 的不可变性,在咱们的场景中,也就是说在相关 action 被触发时,须要返回一个新的数组。数组
const users = (state, action) => {
if (action.type === 'CHANGE_USER_1') {
return [action.payload, ...state.slice(1)]
}
return state
}复制代码
如上代码,当 CHANGE_USER_1 时,咱们对数组的第一项进行更新,使用 slice 方法,不改变原数组的同时返回新的数组。promise
咱们设想全部的 users 数组被 Users 函数式组件渲染:浏览器
import User from './User'
const Users = ({users}) =>
<div>
{
users.map(user => <User {...user} />
}
</div>复制代码
问题的关键在于:users 数组做为 props 出现,当数组中的第 K 项改变时,全部的 组件都会进行 reconciliation 的过程,即便非 K 项并无发生变化。性能优化
这时候,咱们能够引入 React.PureComponent,它经过浅对比规避了没必要要的更新过程。即便浅对比自身也有计算成本,可是通常状况下这都不值一提。bash
以上内容其实已经“老生常谈”了,下面直接进入代码和性能测试环节。
咱们渲染了一个有 200 项的数组:
const arraySize = 200;
const getUsers = () =>
Array(arraySize)
.fill(1)
.map((_, index) => ({
name: 'John Doe',
hobby: 'Painting',
age: index === 0 ? Math.random() * 100 : 50
}));复制代码
注意在 getUsers 方法中,关于 age 属性咱们作了判断,保证每次调用时,getUsers 返回的数组只有第一项的 age 属性不一样。
这个数组将会触发 400 次 re-renders 过程,而且每一次只改变数组第一项的一个属性(age):
const repeats = 400;
componentDidUpdate() {
++this.renderCount;
this.dt += performance.now() - this.startTime;
if (this.renderCount % repeats === 0) {
if (this.componentUnderTestIndex > -1) {
this.dts[componentsToTest[this.componentUnderTestIndex]] = this.dt;
console.log(
'dt',
componentsToTest[this.componentUnderTestIndex],
this.dt
);
}
++this.componentUnderTestIndex;
this.dt = 0;
this.componentUnderTest = componentsToTest[this.componentUnderTestIndex];
}
if (this.componentUnderTest) {
setTimeout(() => {
this.startTime = performance.now();
this.setState({ users: getUsers() });
}, 0);
} else {
alert(`
Render Performance ArraySize: ${arraySize} Repeats: ${repeats}
Functional: ${Math.round(this.dts.Functional)} ms
PureComponent: ${Math.round(this.dts.PureComponent)} ms
Component: ${Math.round(this.dts.Component)} ms
`);
}
}复制代码
为此,咱们采用三种方式设计 组件。
export const Functional = ({ name, age, hobby }) => (
<div>
<span>{name}</span>
<span>{age}</span>
<span>{hobby}</span>
</div>
);复制代码
export class PureComponent extends React.PureComponent {
render() {
const { name, age, hobby } = this.props;
return (
<div>
<span>{name}</span>
<span>{age}</span>
<span>{hobby}</span>
</div>
);
}
}复制代码
export class Component extends React.Component {
render() {
const { name, age, hobby } = this.props;
return (
<div>
<span>{name}</span>
<span>{age}</span>
<span>{hobby}</span>
</div>
);
}
}复制代码
同时,在不一样的浏览器环境下,我得出:
测试硬件环境:
最终结果:
最后,送给你们鲁迅先生的一句话:
“Early optimization is the root of all evil” - 鲁迅
Happy Coding!
PS: 做者 Github仓库 和 知乎问答连接 欢迎各类形式交流。
个人其余几篇关于React技术栈的文章:
React Redux 中间件思想碰见 Web Worker 的灵感(附demo)
了解 Twitter 前端架构 学习复杂场景数据设计
React 探秘 - React Component 和 Element(文末附彩蛋demo和源码)
从setState promise化的探讨 体会React团队设计思想
经过实例,学习编写 React 组件的“最佳实践”
React 组件设计和分解思考
从 React 绑定 this,看 JS 语言发展和框架设计
React 服务端渲染如此轻松 从零开始构建先后端应用
作出Uber移动网页版还不够 极致性能打造才见真章**
React+Redux打造“NEWS EARLY”单页应用 一个项目理解最前沿技术栈真谛**