React 开发实践

尽可能构造「纯净」的组件

React 中的纯净指的是一个组件的 render 方法仅从 props 和 state 两个数据源获取数据,反之,如果一个组件的 render 方法从 props 和 state 两个数据源之外获取了数据,这就不是一个纯净的组件。

保证组件纯净可以大幅降低我们人工保证数据一致性的工作量,保证代码的可靠性。不仅如此,保证组件纯净带来的另一个巨大好处就是你可以通过在组件中引入 PureRenderMixin 这个 React 官方提供的插件来大幅削减不必要的更新。

我们知道,一旦一个组件被触发更新,这个组件的子组件不管数据有没有改变都会被强制更新,React 这么做的目的恐怕是为了照顾那些非纯净组件,从而使得 React 看起来没那么「难用」。但如果我们的组件是纯净的,那么我们完全可以判断这次更新是否需要进行。而 React 也为我们提供了选择的途径,那就是 shouldComponentUpdate 方法。

shouldComponentUpdate 方法应该返回一个布尔值,以指示本次更新是否需要进行,如果返回 false,那么本次更新将被取消。这样我们就可以在 shouldComponentUpdate 方法中比较原始及更新后的 props 和 state,来判断控件是否需要更新,而这正是 PureRenderMixin 插件完成的功能。

所以,保持组件纯净并引入 PureRenderMixin 插件不仅是优化 React 性能的重要方法,也是是 React 的最佳实践。

恰当使用受约束的表单元素

通过保证组件的纯净,组件的数据结构将完美的映射到视图,任何数据的更新将会高效地更新到 DOM。然而,DOM 中还存在一些独特的元素,这些元素本身是有状态的,这就是表单元素。

表单元素由于保存了用户的输入,因此本身就存在一个状态(可以理解为元素的 value 属性)。在 React 中,我们通过在表单元素上绑定事件来将表单元素的状态同步给组件,这在表单元素仅作为接受用户输入的途径时是可行的。

不幸的是,五花八门的需求总是层出不穷。当我们需要将组件状态同步到表单元素状态时,这样的单项绑定就无能为力了,受约束的表单状态便应运而生。

所谓受约束的表单元素,是指表单元素除了通过事件将自身状态同步给组件,还会接收组件的状态,形成双向绑定。最常见的,就是将组件状态绑定给空间元素的 value 属性。相应地,只进行单项绑定的表单元素被称为不受约束的表单元素。

无脑的仅使用受约束的表单元素并没有太大的问题(其实在这中间表单控件应当会经历一次无用的刷新),但我仍然推荐根据应用场景更加精确地使用两种表单元素。

在不可控的方法中谨慎对待 setState

setState 可以说是 React 中最常用的一个方法,但这个最常用的方法背后是一连串的 diff 计算、patch 生成、DOM 更新(关于 Virtual DOM 的原理介绍,网上有很多不错的文章可以自行搜索),可以说是一个非常消耗资源的方法,React 的设计者当然知道这一情况,所以引入了 Batch Update 这一黑科技。

这里我不想赘述太多关于 Batch Update 的实现原理(有兴趣的可以参见这篇文章)。简单来说,Batch Update 实现了将多个 setState 进行合并处理,只进行一次 DOM 更新的目的,这无疑能够大大提高效率。

然而,Batch Update 这一黑科技仍然是有短板的,它只能应用在受 React 「控制」的方法上。简单来讲,你可以将 React 生命周期方法和事件处理方法看作可控的方法,而其他方法都是不可控的方法,包括最常见的异步回调方法。

在不可控的方法中,你每次调用 setState 就伴随着成千上万行代码被同步执行、DOM 被更新。如果调用频繁,必然会导致整个用户界面出现卡顿的情况。

这里的最佳实践是:一个方法只调用一次 setState