组件的生命周期可分成三个状态,如下图所示:
Mounted:React 组件被 render 解析生成对应的 DOM 节点,并被插入到对应的 真是 DOM中。
Updating:一个已经 Mounted 的组件的 state 或者 props 改变时,被重新渲染
Unmounted:一个 Mounted 的组件对应的 DOM 节点被移除真实的 DOM结构
每一个 React状态都封装了对应的 hook (钩子)函数 ,用来绑定对应状态发生时对应的执行函数,每一个状态下都封装了多个 hook 函数。下面我们来看看每个状态下对应执行的函数:
上述图片中列出了每个阶段调用的方法,下面分阶段介绍一下每个方法的作用。
实例化(Mounting)
一个实例初次被创建时所调用的生命周期方法与其他各个后续实例被创建时所调用的方战略有不同。当你首次使用一个组件类时,你会看到下面这些方怯依次被调用:
- getDefaultProps
- getlnitialState
- componentWillMount
- render
- componentDidMount
对于该组件类的所有后续应用,你将会看到下面的方怯依次被调用。
- getlnitialState
- componentWillMount
- render
- componentDidMount
注意, getDefaul tProps 方住已经不在列表中。
getDefaultProps
对于组件类来说,这个方能只会被调用一次。对于那些没有被父辈组件指定props 属性的新建实例来说,这个方传返回的对象可用于为实例设置默认的props 值。
getlnitialState
对于组件的每个实例来说,这个方住的调用次数有且只有一次。在这里你将有机会初始化每个实例的state 。与getDefaultProps 方法不同的是,每次实例创建时该方昌都会被调用一次。在这个方法里,你已经可以访问到t his.props 。
componentWillMount
该方住会在完成首次渲染之前被调用。这也是在render 方法调用前可以修改组件state 的最后一次机会。
render
在这里你会创建一个虚拟DOM ,用来表示组件的输出。对于一个组件来说, render 是唯一一个必需的方毡,并且有特定的规则。render 方怯需要满足下面几点:
- 只能通过this.props 和this.state 访问数据。
- 可以返回n ull 、false 或者任何React 组件。
- 只能出现一个顶级组件(不能返回一组元素)。
必须纯净,意味着不能改变组件的状态或者修改DOM 的输出。
render 方怯返回的结果不是真正的 DOM ,而是一个虚拟的表现, React 随后会把它和真实的 DOM 做对比,来判断是否有必要做出修改。
componentDidMount
在render 方能成功调用并且真实的DOM 已经被渲染之后,你可以在componentDidMount 内部通过this.getDOMNode() 方怯访问到它。这就是你可以用来访问原始DOM 的生命周期钩子函数。比如,当你需要测量渲染出DOM 元素的高度,或者使用计时器来操作它,亦或运行一个自定义的jQuery 插件时,可以将这些操作挂载到这个方位上。
//需要自动补全的字符串
var datasource = [...];
var MyComponent = React.createClass({
render: function () {
return <input •.. />;
},
componentDidMount: function () {
$(this.getDOMNode()).autocomplete({
sources: datasource
});
});
注意:当React 运行在服务搞时, componentDidMount 方法不会被调用。
存在期(updating)
存在期时,组件已经渲染好井且用户可以与它进行交互。你会发现以下方法会依次调用:
- componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
- render
- componentDid Update
componentWillReceiveProps
在任意时刻,组件的props 都可以通过父辈组件来更改。出现这种情况时, componentWillReceiveProps 方告会被调用,你也将获得更改props 对象及更新state 的机会。
shouldComponentUpdate
在组件接收到新的props或者state时被调用,判断组件是否需要更新。返回一个布尔值,如果返回值为 true,则说明需要更新;如果返回 false,则表明不需要更新。返回faIse 则是在告诉React 要跳过调用render 方怯,以及位于render 前后的钩子函数: componentWillUpdate 和 componentDidUpdate 。
注意:在首次渲染期间或者调用了forceUpdate 方法后,这个方法不会被调用。
componentWillUpdate
和componentWillMount 方住类似,组件会在接收到新的props 或者state 进行渲染之前,调用该方怯。
注意,你不可以在该方曲中更新state 或者props。而应该借助 componentWillReceiveProps 方法在运行时更新state 。
componentDidUpdate
和componentDidMount 方法类似,该方法给了我们更新已经渲染好的DOM 的机会。
销毁&清理期(Unmounting)
每当React 使用完一个组件,这个组件就必须从DOM 中卸载随后被销毁。此时,仅有的一个钩子函数会做出晌应,完成所有的清理和销毁工作,这很必要。
componentWillUnmount
最后,随着一个组件从它的层级结构中移除,这个组件的生命也走到了尽头。该方法会在组件被移除之前被调用,让你有机会做一些清理工作。你在componentDidMount 方法中添加的所有任务都需要在该方告中撤销,比如创建的定时器或者添加的事件监听器。
示例:
var Button = React.createClass({
getInitialState: function() {
return {
data:0
};
},
setNewNumber: function() {
this.setState({data: this.state.data + 1})
},
killComponent:function(){
ReactDOM.unmountComponentAtNode( document.getElementById('example') );
},
render: function () {
return (
<div>
<button onClick = {this.setNewNumber}>计数增加</button><br />
<Content myNumber = {this.state.data}></Content>
<button onClick = {this.killComponent}>销毁组件</button>
</div>
);
}
})
var Content = React.createClass({
getDefaultProps:function(){
console.log('getDefaultProps!');
},
getInitialState:function(){
console.log('getInitialState!');
return {
data:0
};
},
componentWillMount:function() {
console.log('componentWillMount!')
},
componentDidMount:function() {
console.log('componentDidMount!')
},
componentWillReceiveProps:function(newProps) {
console.log('componentWillReceiveProps!')
},
shouldComponentUpdate:function(newProps, newState) {
console.log('shouldComponentUpdate:true');
return true;
},
componentWillUpdate:function(nextProps, nextState) {
console.log('componentWillUpdate!');
},
componentDidUpdate:function(prevProps, prevState) {
console.log('componentDidUpdate!')
},
componentWillUnmount:function() {
console.log('componentWillUnmount!')
},
render: function () {
console.log('render');
return (
<div id='content'>
<h3>{this.props.myNumber}</h3>
</div>
);
}
});
ReactDOM.render(
<div>
<Button />
</div>,
document.getElementById('example')
);
在组件 Content
中给出了所有状态下的方法,第一次初始化加载时,依次加载的是 mounting
中的方法;当点击计数增加
按钮时,执行的 updating
阶段中的方法;当点击销毁组件
按钮时,执行的是 unmounting
阶段的方法。
按照上面的操作,在控制台依次打印以下结果: