React生命周期:
componentWillMount
render
componentDidMount
componentWillUpdate
componentDidUpdate
componentWillUnmount
当出现组件嵌套情况时,先渲染父组件,然后再渲染子组件;只有当子组件componentDidMount后,父组件才会componentDidMount。
组件创建时生命周期例子:
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import * as serviceWorker from './serviceWorker';
class App extends Component{
constructor(props){
super(props);
this.state = {
name: 'React'
};
}
render(){
console.log('APP render');
return (<div>
{this.state.name}
{this.state.name && <Son1 name={this.state.name + ' - Son1'}/>}
</div>);
}
componentWillMount(){
console.log('APP will Mount');
}
componentDidMount(){
window.app = this;
console.log('APP Did Mount');
}
componentWillUpdate(){
console.log('APP will Update');
}
componentDidUpdate(){
console.log('APP Did Update');
}
componentWillUnmount(){
console.log('APP Will Unmount');
}
}
class Son1 extends Component {
render() {
console.log('Son1 render');
return (<div>
{this.props.name}
<GrandSon1 name={this.props.name + ' - Grand'}/>
</div>);
}
componentWillMount(){
console.log('Son1 will Mount');
}
componentDidMount(){
console.log('Son1 Did Mount');
}
componentWillUpdate(){
console.log('Son1 will Update');
}
componentDidUpdate(){
console.log('Son1 Did Update');
}
componentWillUnmount(){
console.log('Son1 Will Unmount');
}
}
class GrandSon1 extends Component {
render() {
console.log('GrandSon1 render');
return (<div>
{this.props.name}
</div>);
}
componentWillMount(){
console.log('GrandSon1 will Mount');
}
componentDidMount(){
console.log('GrandSon1 Did Mount');
}
componentWillUpdate(){
console.log('GrandSon1 will Update');
}
componentDidUpdate(){
console.log('GrandSon1 Did Update');
}
componentWillUnmount(){
console.log('GrandSon1 Will Unmount');
}
}
ReactDOM.render(<App />, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
上面代码输出日志为:
App will mount
App render
Son1 will mount
Son1 render
GrandSon1 will mount
GrandSon1 render
GrandSon1 did mount
Son1 did mount
App did mount
组件更新时生命周期例子:
app.setState({name: 'Vue'});
控制台输出日志为:
App will update
App render
Son1 will update
Son1 render
GrandSon1 will update
GrandSon1 render
GrandSon1 Did update
Son1 Did update
App Did update
组件卸载(销毁)时生命周期例子:
APP组件render方法:
render(){
console.log('APP render');
return (<div>
{this.state.name}
{this.state.name && <Son1 name={this.state.name + ' - Son1'}/>}
</div>);
}
设置name为’’,来销毁Son1组件:
app.setState({name: ''});
控制台输出日志如下:
App will update
App render
Son1 will unmount
GrandSon1 will unmount
App Did update
组件上下文例子:
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import * as serviceWorker from './serviceWorker';
import PropTypes from 'prop-types'
class App extends Component{
getChildContext(){
return {
color: 'Red'
};
}
constructor(props){
super(props);
this.state = {
name: 'React'
};
}
render(){
console.log('APP render');
return (<div>
{this.state.name && <Son1 name={this.state.name + ' - Son1'}/>}
</div>);
}
componentWillMount(){
console.log('APP will Mount');
}
componentDidMount(){
window.app = this;
console.log('APP Did Mount');
}
componentWillUpdate(){
console.log('APP will Update');
}
componentDidUpdate(){
console.log('APP Did Update');
}
componentWillUnmount(){
console.log('APP Will Unmount');
}
}
App.childContextTypes = {
color: PropTypes.string
};
class Son1 extends Component {
render() {
console.log('Son1 render');
return (<div>
{this.props.name && <GrandSon1 name={this.props.name + '- Grand'}/>}
</div>);
}
componentWillMount(){
console.log('Son1 will Mount');
}
componentDidMount(){
console.log('Son1 Did Mount');
}
componentWillUpdate(){
console.log('Son1 will Update');
}
componentDidUpdate(){
console.log('Son1 Did Update');
}
componentWillUnmount(){
console.log('Son1 Will Unmount');
}
}
class GrandSon1 extends Component {
render() {
console.log('GrandSon1 render');
return (<div>
{this.props.name} - {this.context.color}
</div>);
}
componentWillMount(){
console.log('GrandSon1 will Mount');
}
componentDidMount(){
console.log('GrandSon1 Did Mount');
}
componentWillUpdate(){
console.log('GrandSon1 will Update');
}
componentDidUpdate(){
console.log('GrandSon1 Did Update');
}
componentWillUnmount(){
console.log('GrandSon1 Will Unmount');
}
}
GrandSon1.contextTypes = {
color: PropTypes.string
};
ReactDOM.render(<App />, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
当组件嵌套层次比较深的时候,可以利用这种方式将父组件数据传递到子组件。要定义父组件的childContextTypes,实现父组件的getChildContext方法,然后再定义一下子组件的contextTypes就可以在子组件中使用这个上下文数据了。
Notes:
state和props的相同之处:
1. 改变会触发render函数(UI的改变);
state和props的不同之处:
1. state是可读可写的,props是只读的;
- state是组件内部的数据,props来自父组件(外部);
state变化例子:
在下面的例子中,App的render方法中并没有用到state,但是当state发生变化时候(app.setState({name: ‘Vue’})),App组件会重新render。
日志如下:
APP will Update
APP render
APP Did Update
class App extends Component{
constructor(props){
super(props);
this.state = {
name: 'React'
};
}
render(){
console.log('APP render');
return (<div>
APP
</div>);
}
componentWillMount(){
console.log('APP will Mount');
}
componentDidMount(){
window.app = this;
console.log('APP Did Mount');
}
componentWillUpdate(){
console.log('APP will Update');
}
componentDidUpdate(){
console.log('APP Did Update');
}
componentWillUnmount(){
console.log('APP Will Unmount');
}
}