React由于他的性能而著名。由于他有一个虚拟DOM层而且只有在须要时才更新真实DOM。即便是一样地信息这也比一直直接更新DOM要快不少。可是,React的智能仅此而已(目前为止),咱们的任务是知道React的预期行为以及限制,这样咱们才不会意外损失性能。javascript
咱们须要关注的一方面是React如何决定何时从新渲染组件。不是从新渲染DOM节点,只是调用render
方法来改变虚拟DOM。咱们能够经过告诉React何时须要渲染何时不须要渲染来帮助React。让咱们依次来看看这些。html
只有在组件的state变化时才会出发组件的从新渲染。状态的改变能够由于props
的改变,或者直接经过setState
方法改变。组件得到新的状态而后React决定是否应该从新渲染组件。不幸的是,React难以置信简单地将默认行为设计为每次都从新渲染。java
组件改变?从新渲染。父组件改变?从新渲染。一部分没有致使视图改变的props改变?从新渲染。react
class Todo extends React.Component { componentDidMount() { setInterval(() => { this.setState(() => { console.log('setting state'); return { unseen: "does not display" } }); }, 1000); } render() { console.log('render called'); return (<div>...</div>); } }
在这个(很是刻意的)例子中,Todo
将会每秒从新渲染依次,即便render
方法根本没有使用unseen
。事实上,unseen
值甚至都不改变。你能够在CodePen里查看这个例子的实际版本。git
好吧,可是每次都从新渲染没有什么帮助。github
个人意思是,我很是感谢React的细心谨慎。若是状态改变可是组件没有正确渲染的话更糟。权衡之下,每次都从新渲染绝对是一个安全的选择。安全
可是从新渲染的时间成本看起来很是昂贵(例子里很是夸张地表现了出来)。性能优化
是的,在没必要要的时候从新渲染会浪费循环而且不是一个好的想好。可是,React不能知道何时能够安全的跳太重新渲染,因此React不管是否重要每次都从新渲染。工具
咱们如何告诉React跳太重新渲染?性能
那就是第二点要说的内容。
shouldComponentUpdate
方法shouldComponentUpdate
方法默认返回true
,这就是致使每次更新都从新渲染的缘由。可是你能够在须要优化性能时重写这个方法来让React更智能。比起让React每次都从新渲染,你能够告诉React你何时不像触发从新渲染。
当React将要渲染组件时他会执行shouldComponentUpdate
方法来看它是否返回true
(组件应该更新,也就是从新渲染)。因此你须要重写shouldComponentUpdate
方法让它根据状况返回true
或者false
来告诉React何时从新渲染何时跳太重新渲染。
当你使用shouldComponentUpdate
方法你须要考虑哪些数据对与从新渲染重要。让咱们回到这个例子。
正如你所看到的,咱们只想在title
和done
属性改变的时候从新渲染Todo
。咱们不关心unseen
是否改变,因此我没有把它包含在shouldComponentUpdate
方法中。
当React渲染Todo
组件(经过setState
触发)他会首先检查状态是否改变(经过props
和state
)。假设状态改变了(由于咱们显式地调用了setState
因此这会发生)React会检查Todo
的shouldComponentUpdate
方法。React会根据shouldComponentUpdate
方法返回值为true
或者false
来决定从哪里渲染。
更新后的代码仍然会每秒调用一次setState
可是render
只有在第一次加载时(或者title
或done
属性改变后)才会调用。你能够在这里看到。
看起来有不少工做去作。
是的,这个例子很是冗长由于有两个属性(title
和done
)须要关注而且只有一个能够忽略(unseen
)。根据你的数据可能仅检查一个或两个属性而且忽略其余会更有意义。
重要提示
当子组件的的state变化时, 返回false并不能阻止它们重渲染。
– Facebook的React文档
这做用于子组件的状态而不是他们的props
。因此若是一个子组件内部管理了一些他本身的状态(使用他本身的setState
),这仍然会更新。可是若是父组件的shouldComponentUpdate
方法返回了false
就不会传递更新后的props
给他的子组件,因此子组件不会重渲染,即便他们的props
变化了。
编写而且在shouldComponentUpdate
方法中运行计算的时间成本可能会很昂贵,因此你须要确保值得作。在写shouldComponentUpdate
方法前你能够测试React一个周期默认会消耗多少时间。有了这个信息作参考,在作性能优化时你能够作一个不盲目的决定。
使用React的性能工具去发现浪费的周期:
Perf.start() // Do the render Perf.stop() Perf.printWasted()
哪个组件浪费了不少渲染周期?你怎么经过shouldComponentUpdate
方法让他们更智能?试着使用性能测试工具来比较他们的性能。