组件的生命周期
组件本质上是伏态机,输入确定,输出一定确定。
状态发生转换时会触发不同的钩子函数,从而让开发者有机会做出响应。
可以用事件的思国思路来理解状态。
初始化->运行中->销毁
初始化
getDefaultProps(只会在第一个实例初始化时被调用)->getInitialState->componentWillMount->render->componentDidMount
运行中
componentWillReceiveProps->shouldComponentUpdate->componentWillUpdate->render->componentDidUpdate
销毁
componentWillUnmount
初始化阶段
初始化阶段可以使用的函数:
- getDefaultProps: 只调用一次,实例之间共享引用
- getInitialState: 初始化每个实例特有的状态
- componentWillMount: render之前最后一次修改状态的机会
- render: 只能访问this.props和this.state,只有一个顶层组件(不能返回数组),不允许修改状态和DOM输出
- componentDidMount: 成功render并渲染完成真实DOM后触发,可以修改DOM
实例演示:
var style = {
color: "red",
border: "1px solid #000",
};
var HelloWorld = React.createClass({
getDefaultProps: function () {
console.log('getDefaultProps, 1')
},
getInitialState: function () {
console.log('getInitialState, 2');
return null;
},
componentWillMount: function () {
console.log('componentWillMount, 3');
},
render: function () {
console.log('render, 4');
return <p ref="childp">Hello, {(function (obj) {
if (obj.props.name) {
return obj.props.name;
} else {
return "World";
}
})(this)}</p>;
},
componentDidMount: function () {
console.log('componentDidMount, 5');
}
});
ReactDOM.render(<div style={style}><HelloWorld></HelloWorld></div>, document.body)
$(function () {
var count = 0;
var style = {
color: "red",
border: "1px solid #000",
};
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 + count}</p>;
},
componentDidMount: function () {
console.log('componentDidMount, 5');
$(ReactDOM.findDOMNode(this)).append('surprise!');
}
});
ReactDOM.render(<div style={style}><HelloWorld></HelloWorld><br/><HelloWorld></HelloWorld></div>, document.body);
})();
运行中阶段
运行中阶段可以使用的函数:
- componentWillReceiveProps: 父组件修改属性触发,可以修改新属性、修改状态
- shouldComponentUpdate: 返回false会阻止render调用
- componentWillUpdate: 不能合修改属性和状态
- render: 只能访问this.props和this.state,只有一个顶层组件,不允许修改状态和DOM输出
- componentDidUpdate: 可以修改DOM
实例演示:
var style = {
color: "red",
border: "1px solid #000",
};
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>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.body);
父组件改变子组件的属性:
$(document).ready(function() {
var style = {
color: "red",
border: "1px solid #000",
};
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>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.body);
});
销毁阶段
$(document).ready(function() {
var style = {
color: "red",
border: "1px solid #000",
};
var HelloWorld = React.createClass({
render: function () {
console.log('render 4');
return <p>Hello, {this.props.name ? this.props.name : "World"}</p>;
},
componentWillUnmount: function() {
console.log("BOOOOOOOOOOOOOOOOOOOOOM!");
},
});
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.body);
});
上面示例中,一开始生成HelloWorld组件,先生成HelloWorld组件,当我们输入123,生成
$(document).ready(function () {
var style = {
color: "red",
border: "1px solid #000",
};
var HelloWorld = React.createClass({
render: function () {
console.log('render 4');
return <p>Hello, {this.props.name ? this.props.name : "World"}</p>;
},
componentWillUnmount: function () {
console.log("BOOOOOOOOOOOOOOOOOOOOOM!");
},
});
var HelloUniverse = React.createClass({
getInitialState: function () {
return {name: ''};
},
handleChange: function (event) {
if (event.target.value == "123") {
ReactDOM.unmountComponentAtNode(document.getElementsByTagName('body')[0]); //参数为render时第二个参数节点,即下面的body
return;
}
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.body);
});
上面示例值接删除了该DOM节点。