React组件的生命周期

本文由清尘发表于2016-07-25 11:01属于javascript分类

在组件的整个生命周期中,随着该组件的props或者state发生改变,它的DOM表现也将有相应的变化。

一个组件就是一个状态机:对于特定的输入,它总会返回一致的输出。

React为每个组件提供了生命周期钩子函数去响应不同的时刻————创建时、存在期及销毁时。

生命周期方法

一个实例初次被创建时所调用的生命周期方法与其他各个后续实例被创建时所调用的方法略有不同。当你首次使用一个组件类时,你会看到下面这些方法依次被调用:

实例化:

getDefaultProps

getInitialState

componentWillMount

render

componentDidMount

存在期:

componentWillReceiveProps

shouldComponentUpdate

componentWillUpdate

render

componentDidUpdate

销毁&清理期

最后,当该组件被使用完成后,componentWillUnmount方法将会被调用,目的是给这个实例提供清理自身的机会。

getDefaultProps

对于组件类来说,这个方法只会被调用一次。对于那些没有被父辈组件指定props属性的新建实例来说,这个方法返回的对象可用于为实例设置默认的props值。

getInitialState

对于组件的每个实例来说,这个方法的调用次数有且只有一次。在这里你将有机会初始化每个实例的state。与getDefaultProps方法不同的是,每次实例创建时该方法都会被调用一次。在这个方法里,你已经可以访问到this.props。

componentWillMount

该方法会在完成首次渲染之前被调用。这也是在render方法调用前可以修改组件state的最后一次机会。

render

在这里你会创建一个虚拟DOM,用来表示组件的输出。对于一个组件来说,render是唯一一个必需的方法,并且有特定的规则。render方法需要满足下面几点:

只能通过this.props和this.state访问数据

可以返回null、false或者任何React组件。

只能出现一个顶级组件(不能返回一组元素)。

必须纯净,意味着不能改变组件的状态或者修改DOM的输出。

render方法返回的结果不是真正的DOM,而是一个虚拟的表现,React随后会把它和真实的DOM做对比,来判断是否有必要做出修改。

componentDidMount

在render方法成功调用并且真实的DOM已经被渲染之后,你可以在componentDidMount内部通过this.getDOMNode()方法访问到它。

这就是你可以用来访问原始DOM的生命周期钩子函数。比如,当你需要测量渲染出DOM元素的高度,或者使用计时器来操作它,亦或运行一个自定义的jQuery插件时,可以将这些操作挂载到这个方法上。

举例来说,假设需要在一个通过React渲染出的表单元素上使用jQuery UI的Autocomplete插件,则可以这样使用它:

var datasource = [...];
var MyComponent = React.createClass({
    render:function(){
        return <input .../>;
    },
    componentDidMount:function(){
    $(this.getDOMNode()).autocomplete({
        sources: datasource
    })
    }
})

存在期

此时,组件已经渲染好并且用户可以与它进行交互。通常是通过一次鼠标点击、手指点按或者键盘事件来触发一个事件处理器。随着用户改变了组件或者整个应用的state,便会有新的state流入组件树,并且我们将会获得操控它的机会。

componentWillReceiveProps

在任意时刻,组件的props都可以通过父辈组件来更改。出现这种情况时,componentWillReceiveProps方法会被调用,你也将获得更改props对象及更新state的机会。

比如,在我们的问卷制作工具中有一个AnswerRadioInput组件,允许用户切换一个单选框。父辈组件能够改变这个布尔值,并且我们可以对其做出响应,比如基于父辈组件输入的props更新组件自身的内部state。

componentWillReceiveProps: function(nextProps){
    if(nextProps.checked !== undefined){
        this.setState({
            checked: nextProps.checked
        })
    }
}

shouldComponentUpdate

React非常快。不过你还可以让它更快————通过调用shouldComponentUpdate方法在组件渲染时进行精确优化。

如果你确定某个组件或者它的任何子组件不需要渲染新的props或者state,则该方法会返回false。

返回false则是在告诉React要跳过调用render方法,以及位于render前后的钩子函数:componentWillUpdate和componentDidUpdate。

该方法是非必需的,并且大多数情况下没有必要在开发中使用。草率地使用它可能导致不可思议的bug,所以最好等到能够准确地测量出应用的瓶颈后,再去选择要在何处进行恰当的优化。

componentWillUpdate

和componentWillMount方法类似,组件会在接收到新的props或者state进行渲染之前,调用该方法。

注意,你不可以在该方法中更新state或者props。而应该借助componentWillReceiveProps方法在运行时更新state。

componentDidUpdate

和componentDidMount方法类似,该方法给了我们更新已经渲染好的DOM的机会。

销毁&清理期

每当React使用完一个组件,这个组件就必须从DOM中卸载随后被销毁。此时,仅有的一个钩子函数会做出响应,完成所有的清理和销毁工作,这很必要。

componentWillUnmount

最后,随着一个组件从它的层级结构中移除,这个组件的生命也走到了尽头。该方法会在组件被移除之前被调用,让你有机会做一些清理工作。你在componentDidMount方法中添加的所有任务都需要在该方法中撤销,比如创建的定时器或者添加的事件监听器。

React生命周期方法提供了精心设计的钩子函数,会伴随组件的整个生命周期。和状态机类似,每个组件都被设计成了能够在整个生命周期中输出稳定、语义化的标签。

组件不会独立存在。随着父组件将props推送给它们的子组件,以及那些子组件渲染它们自身的子组件,你必须谨慎地考虑数据是如何流经整个应用的。