React怎么判断何时该从新渲染组件?

React由于他的性能而著名。由于他有一个虚拟DOM层而且只有在须要时才更新真实DOM。即便是一样地信息这也比一直直接更新DOM要快不少。可是,React的智能仅此而已(目前为止),咱们的任务是知道React的预期行为以及限制,这样咱们才不会意外损失性能。javascript

咱们须要关注的一方面是React如何决定何时从新渲染组件。不是从新渲染DOM节点,只是调用render方法来改变虚拟DOM。咱们能够经过告诉React何时须要渲染何时不须要渲染来帮助React。让咱们依次来看看这些。html

1. 组件的状态发生改变

只有在组件的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跳太重新渲染?性能

那就是第二点要说的内容。

2. shouldComponentUpdate方法

shouldComponentUpdate方法默认返回true,这就是致使每次更新都从新渲染的缘由。可是你能够在须要优化性能时重写这个方法来让React更智能。比起让React每次都从新渲染,你能够告诉React你何时不像触发从新渲染。

当React将要渲染组件时他会执行shouldComponentUpdate方法来看它是否返回true(组件应该更新,也就是从新渲染)。因此你须要重写shouldComponentUpdate方法让它根据状况返回true或者false来告诉React何时从新渲染何时跳太重新渲染。

当你使用shouldComponentUpdate方法你须要考虑哪些数据对与从新渲染重要。让咱们回到这个例子。

正如你所看到的,咱们只想在titledone属性改变的时候从新渲染Todo。咱们不关心unseen是否改变,因此我没有把它包含在shouldComponentUpdate方法中。

当React渲染Todo组件(经过setState触发)他会首先检查状态是否改变(经过propsstate)。假设状态改变了(由于咱们显式地调用了setState因此这会发生)React会检查TodoshouldComponentUpdate方法。React会根据shouldComponentUpdate方法返回值为true或者false来决定从哪里渲染。

更新后的代码仍然会每秒调用一次setState可是render只有在第一次加载时(或者titledone属性改变后)才会调用。你能够在这里看到。

看起来有不少工做去作。

是的,这个例子很是冗长由于有两个属性(titledone)须要关注而且只有一个能够忽略(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方法让他们更智能?试着使用性能测试工具来比较他们的性能。

相关文章
相关标签/搜索