组件的生命周期
组件在react的生命周期中主要经历三个阶段:实例化、存在期和销毁时。
React.js在组件生命周期的每个阶段暴露接口或挂钩方法。
实例化
当组件在客户端被实例化,第一次被创建时,以下方法依次被调用:
1、getDefaultProps
2、getInitialState
3、componentWillMount
4、render
5、componentDidMount
当组件在服务端被实例化,首次被创建时,以下方法依次被调用:
1、getDefaultProps
2、getInitialState
3、componentWillMount
4、render
componentDidMount 不会在服务端被渲染的过程中调用。
getDefaultProps
var U serInformation = React.createClass({
getDefaultProps: function() {
return {
name: 'Nobody',
score: 0
}
}
});
在创建组件的任何实例之前,只调用getDefaultProps()方法一次。 所以你应该避免在getDefaultProps()方法中使用this.props。其返回的对象可以用于设置默认的 props(properties的缩写) 值。
getInitialState
const userScore = [
{
name: 'Tom',
score: 55
},
{
name: 'Jerry',
score: 80
}
]
var UserInformation = React.createClass({
getInitialState: function() {
return {
players: userScore
}
},
});
初始化组件的 state 的值,其返回值会赋值给组件的 this.state 属性。getInitialState()方法仅在实例化组件之前调用一次。
componentWillMount
服务器端和客户端都只调用一次,在初始化渲染执行之前立刻调用。
它也是在组件WillMount()中设置初始状态值的好地方。
class UserInformation extends React.Component {
componentWillMount() {
this.setState({
isPassed: this.props.score >= 60
});
alert('componentWillMount => ' + this.props.name);
console.log('componentWillMount => ' + this.props.name);
}
// ...
}
render
该方法会创建一个虚拟DOM,用来表示组件的输出。对于一个组件来讲,render方法是唯一一个必需的方法。render方法需要满足下面几点:
- 只能通过 this.props 和 this.state 访问数据(不能修改)
- 可以返回 null,false 或者任何React组件
- 只能出现一个顶级组件,不能返回一组元素
- 不能改变组件的状态
- 不能修改DOM的输出
根据 state 的值,生成页面需要的虚拟 DOM 结构,并返回该结构。
componentDidMount
在渲染完成后调用此方法,此时的DOM已为真实DOM,可以再该方法中通过 this.getDOMNode() 访问到真实的 DOM(推荐用ReactDOM.findDOMNode())。
class Scroll extends React.Component {
constructor(props) {
super(props);
this._handleScroll = this.handleScroll.bind(this);
}
handleScroll() {}
componentDidMount() {
alert('componentDidMount in NoticeBoard');
window.addEventListener('scroll', this._handleScroll);
}
// ...
}
由于组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。有时需要从组件获取真实 DOM 的节点,这时就要用到 ref 属性。
需要注意的是,由于 this.refs.[refName] 属性获取的是真实 DOM ,所以必须等到虚拟 DOM 插入文档以后,才能使用这个属性,否则会报错。
存在期
此时组件已经渲染好并且用户可以与它进行交互,比如鼠标点击,手指点按,或者其它的一些事件,导致应用状态的改变,你将会看到下面的方法依次被调用
1、componentWillReceiveProps
2、shouldComponentUpdate
3、componentWillUpdate
4、render
5、componentDidUpdate
componentWillReceiveProps
当组件接收到新的 props 时,会触发该函数。在改函数中,通常可以调用 this.setState 方法来完成对 state 的修改。
class App extends React.Component {
componentWillReceiveProps(nextProps) {
// Calculate state according to props changes
this.setState({
isPassed: nextProps.score
});
}
}
shouldComponentUpdate
在接收到新的props或state时,将在渲染之前调用该函数。 在初始渲染时不会调用此方法。
shouldComponentUpdate()默认情况下返回true。
这种方法通常是一个机会,以防止考虑性能的不必要的渲染。 只要让shouldComponentUpdate()返回false,那么组件的render()方法将被完全跳过,直到下一个props或state发生更改。
class App extends React.Component {
shouldComponentUpdate(nextProps, nextState) {
// Don't rerender if score doesn't change,
if ( nextProps.score == this.props.score ) {
return false;
}
return true;
}
}
componentWillUpdate
这个方法和 componentWillMount 类似,在组件接收到了新的 props 或者 state 即将进行重新渲染前,componentWillUpdate(object nextProps, object nextState) 会被调用,注意不要在此方面里再去更新 props 或者 state。
componentDidUpdate
这个方法和 componentDidMount 类似,在组件的更新刷新到DOM后componentDidUpdate(object prevProps, object prevState) 会被调用。 这种方法不是初始渲染的方法。可以在这里访问并修改 DOM。
销毁时
componentWillUnmount
在组件被卸载或从DOM中移除之前立即调用。
使用它作为执行清理操作的机会。 例如,在此处解除绑定事件、销毁无效侦听器以避免内存泄漏。
class App extends React.Component {
componentWillUnmount() {
window.removeEventListener('scroll', this._handleScroll);
}
}