原文链接
https://medium.com/missive-ap...
原作者
Philippe Lehoux
利用js原生方法替换react component实现性能提升
现在我们正在用React实现一个具有邮件收发和即时聊天功能的客户端工具。
如图所示,通过鼠标和键盘的上下箭头可以从左侧的导航栏切换不同的对话。为了防止用户感觉卡顿,所有的动作都需要在毫秒级完成。
一段对话可能包含成千上百条的评论、邮件和各种各样的事件,而所有的这些内容都由各种组件实现。为了提升在不同对话间切换时的渲染速度,我们开始着手将一些stateful组件变为stateless组件(此处原文叫做Function component)。
举个栗子,之前的一个组件是这样的:
class Avatar extends React.Component {
render() {
return <img src={this.props.url} />;
}
}
经过转换之后变为:
const Avatar = (props) => {
return <img src={props.url} />;
}
其实一个Functional component就是一个简单的js函数,这个函数返回要渲染的元素。Functional component也被称为stateless组件。
我们认为通过将stateful组件变为stateless组件后性能会有立竿见影的提升,因为当我们使用stateful组件时,在通过导航切换不同对话时React会不断的进行上百次的mount和unmount处理,而stateless本身只是基础的js函数,它的触发就像触发生命周期函数一样简单,避免了多次的mount和unmount处理,从而节省了渲染时间。
然而理想是丰满的,现实是残酷的。。。
那么我们要怎么才能跳过React的内部机制,不将stateless组件的内容通过react componet渲染,而是直接通过调用函数的方式渲染呢?
其实很简单,我们只需要改变一下调用方式即可:
ReactDOM.render(
<div>
- <Avatar url={avatarUrl} />
+ {Avatar({ url: avatarUrl })}
<div>{commentBody}</div>
</div>,
mountNode
);
// Compiled JavaScript
ReactDOM.render(React.createElement(
'div',
null,
- React.createElement(Avatar, { url: avatarUrl }),
+ Avatar({ url: avatarUrl }),
React.createElement(
'div',
null,
commentBody
)
), mountNode);
通过性能测试可以看出如果只是通过将stateful组件改为stateless组件,而不改变调用方式,渲染速度只提升了6%;而改变调用方式后,速度提升了45%。
就像上面的性能测试中展现出来的一样,这些修改很适用于提升像我们的应用一样通过普通的stateful组件方式渲染会触发过多的mount和unmount事件的应用场景。