一、什么是生命周期
组件本质上是状态机,输入确定,输出一定确定。
状态发生转换时会触发不同的钩子函数,从而让开发者有机会做出响应。
组件的生命周期分为初始化阶段、运行中阶段、销毁阶段。
二、初始化阶段
根据编写的组件代码生成组件化实例。
1.可以使用的钩子函数
getDefaultProps:获取实例的默认属性。只调用一次,实例之间共享应用。
getInitialState:获取实例的初始化状态。初始化每个实例特有的状态。
componentWillMount:组件即将被渲染。render之前最后一次修改状态的机会。
render:组件再render函数中生成虚拟的DOM,也就是JXS,最后由render将虚拟的DOM节点渲染成真正的DOM节点。只能访问this.props和this.state,只有一个顶层组件,不允许修改状态和DOM输出。
componentDidMount:组件被装载后调用,组件已经被渲染到页面上。成功render并渲染完成真实DOM之后触发,可以修改DOM。
触发顺序由上到下。
2.实例
2.1查看触发顺序
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import { DatePicker } from 'antd';
import { Menu, Dropdown, Icon } from 'antd';
var HelloWorld = React.createClass({
getDefaultProps:function(){
console.log("getDefaultProps,1");
},
getInitialState:function(){
console.log("getInitialState,2");
return null;
},
componentWillMount:function(){
console.log("componentWllMount,3");
},
render:function(){
return <p ref="childp">Hello,{(function (obj){
console.log("render,4");
if (obj.props.name) {
return obj.props.name
}else {
return "World"
}
})(this)}</p>
},
componentDidMount:function(){
console.log("componentDidMount,5");
},
});
ReactDOM.render(
<div><HelloWorld></HelloWorld></div>,
document.getElementById('root')
);
2.2各个函数的正确用法
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import { DatePicker } from 'antd';
import { Menu, Dropdown, Icon } from 'antd';
import $ from 'jquery';
$(document).ready(
function() {
var count = 0;
var style = {
color: "red",
border: "1px #000 solid",
};
var HelloWorld = React.createClass({
getDefaultProps: function () {
console.log("getDefaultProps, 1");
return {name: "Tom"};
},
getInitialState: function () {
console.log("getInitialState, 2");
return {myCount: count++,
ready: false};
},
componentWillMount: function () {
console.log("componentWillMount, 3");
this.setState({ready: true});
},
render: function () {
console.log("render, 4");
return <p ref="childp">Hello, {this.props.name ? this.props.name : "World"}<br/>{"" + this.state.ready} {this.state.myCount}</p>;
},
componentDidMount: function () {
console.log("componentDidMount, 5");
$(ReactDOM.findDOMNode(this)).append("surprise!");
},
});
ReactDOM.render(
<div style={style}><HelloWorld></HelloWorld><br/><HelloWorld></HelloWorld></div>,
document.getElementById('root')
);
}
);
三、运行中阶段
对于实例来说,绝大多数时间处在运行中,运行中实例的状态可能发生改变,从而触发一系列钩子函数,最终这些组件可能导致组件重新渲染。注意:这里说的是可能导致页面重新渲染,有些组件不能导致页面重新渲染,比如,input组件。
1.可以使用的钩子函数
componentWillReceiveProps:组件将要接收到属性的时候调用。父组件修改属性触发,可以修改新属性、修改状态。
shouldComponentUpdate:组件是否需要更新,当组件接收到新属性或新状态的时候会被调用。如果返回false,后面的render函数就不会被调用,调高性能。
componentWillUpdate:组件将会被更新。不能修改属性和状态。
render:跟初始化阶段的render函数一样。
componentDidUpdate:组件已经被更新。可以修改DOM。
2.实例
2.1查看触发顺序
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import { DatePicker } from 'antd';
import { Menu, Dropdown, Icon } from 'antd';
import $ from 'jquery';
var style = {
color: "red",
border: "1px #000 solid",
};
var HelloWorld = React.createClass({
componentWillReceiveProps: function () {
console.log("componentWillReceiveProps 1");
},
shouldComponentUpdate: function () {
console.log("shouldComponentUpdate 2");
return true;
},
componentWillUpdate: function () {
console.log("componentWillUpdate 3");
},
render: function () {
console.log("render 4");
return <p ref="childp">Hello, {this.props.name ? this.props.name : "World"}</p>;
},
componentDidUpdate: function () {
console.log("componentDidUpdate 5");
},
});
var HelloUniverse = React.createClass({
getInitialState:function(){
return {name:''}
},
handleChange:function(event){
this.setState({name:event.target.value});
},
render:function(){
return <div>
<HelloWorld name={this.state.name}></HelloWorld>
<br/>
<input type="text" onChange={this.handleChange}/>
</div>
}
});
ReactDOM.render(
<div style={style}><HelloUniverse></HelloUniverse></div>,
document.getElementById('root')
);
2.2各个函数的正确用法
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import { DatePicker } from 'antd';
import { Menu, Dropdown, Icon } from 'antd';
import $ from 'jquery';
$(document).ready(
function(){
var style = {
color: "red",
border: "1px #000 solid",
};
var HelloWorld = React.createClass({
componentWillReceiveProps: function (newProps) {
console.log("componentWillReceiveProps 1");
console.log(newProps);
},
shouldComponentUpdate: function () {
console.log("shouldComponentUpdate 2");
return true;
},
componentWillUpdate: function () {
console.log("componentWillUpdate 3");
},
render: function () {
console.log("render 4");
return <p ref="childp">Hello, {this.props.name ? this.props.name : "World"}</p>;
},
componentDidUpdate: function () {
console.log("componentDidUpdate 5");
$(ReactDOM.findDOMNode(this)).append(" surprise!");
},
});
var HelloUniverse = React.createClass({
getInitialState:function(){
return {name:''}
},
handleChange:function(event){
this.setState({name:event.target.value});
},
render:function(){
return <div>
<HelloWorld name={this.state.name}></HelloWorld>
<br/>
<input type="text" onChange={this.handleChange}/>
</div>
}
});
ReactDOM.render(
<div style={style}><HelloUniverse></HelloUniverse></div>,
document.getElementById('root')
);
}
);
四、销毁阶段
当我们不使用组件的时候组件的实例就会被销毁。
1.可以使用的钩子函数
componentWillUnmount:会在组件真正被销毁前调用,给开发者机会,来进行一些清理操作。在删除组件之前进行清理操作,比如计时器和事件监听器。
2.实例
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import { DatePicker } from 'antd';
import { Menu, Dropdown, Icon } from 'antd';
import $ from 'jquery';
var style = {
color: "red",
border: "1px #000 solid",
};
var HelloWorld = React.createClass({
render: function () {
console.log("render 4");
return <p ref="childp">Hello, {this.props.name ? this.props.name : "World"}</p>;
},
componentWillUnmount:function(){
console.log("B000000000000000000000M!");
},
});
var HelloUniverse = React.createClass({
getInitialState:function(){
return {name:''}
},
handleChange:function(event){
this.setState({name:event.target.value});
},
render:function(){
if (this.state.name == "123") {
return <div>123</div>
}
return <div>
<HelloWorld name={this.state.name}></HelloWorld>
<br/>
<input type="text" onChange={this.handleChange}/>
</div>
}
});
ReactDOM.render(
<div style={style}><HelloUniverse></HelloUniverse></div>,
document.getElementById('root')
);