生命周期(Life Cycle):是指一个对象的生老病死。此处的生命周期指的是在对应的框架中一个组件(对象)或程序从创建到销毁的过程。
React生命周期图
React生命周期详解
React生命周期大体分为四个周期: 初始化、挂载、更新、卸载。
1.初始化期:
- getDefautProps (es6: static defaultProps)
- getInitialState (es6: constructor(props))
2.挂载期:
- componentWillMount
- render
- componentDidMount
3.更新期
- componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
- render
- componentDidUpdate
4.卸载
- componentWillUnmount
示例演示
初始化和挂载期代码演示:
src/index.js
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<App />,
document.getElementById('root')
);
src/App.js
class App extends Component {
static defaultProps = {
title: (() => {
console.log(`defaultProps 初始期`)
return 'app';
})()
}
constructor(props) {
super(props);
this.state = {
name: (() => {
console.log(`this.state constructor时期`);
return 'react'
})()
}
}
componentWillMount() {
console.log(`componentWillMount 方法`)
}
componentDidMount() {
console.log(`componentDidMount 方法`)
}
componentWillReceiveProps() {
console.log(`componentWillReceiveProps 方法`)
}
shouldComponentUpdate() {
console.log(`shouldComponentUpdate 方法`)
}
componentWillUpdate() {
console.log(`componentWillUpdate 方法`)
}
componentDidUpdate() {
console.log(`componentDidUpdate 方法`)
}
componentWillUnmount() {
console.log(`componentWillUnmount 方法`)
}
render() {
console.log(`render 方法`)
return <div>{this.props.title} {this.state.name}</div>
}
}
export default App;
运行结果:
App.js:6 defaultProps 初始期
App.js:15 this.state constructor时期
App.js:22 componentWillMount 方法
App.js:50 render 方法
App.js:26 componentDidMount 方法
更新期代码演示:
更新器分两种情况,一种是自身变化(state),另一种是父组件变化(props)。
自身state变化的情况:
src/App.js
class App extends Component {
static defaultProps = {
title: (() => {
console.log(`defaultProps 初始期`)
return 'app';
})()
}
constructor(props) {
super(props);
this.state = {
name: (() => {
console.log(`this.state constructor时期`);
return 'react'
})()
}
}
componentWillMount() {
console.log(`componentWillMount 方法`)
}
componentDidMount() {
console.log(`componentDidMount 方法`)
}
componentWillReceiveProps() {
console.log(`componentWillReceiveProps 方法`)
}
shouldComponentUpdate() {
console.log(`shouldComponentUpdate 方法`)
return true;
}
componentWillUpdate() {
console.log(`componentWillUpdate 方法`)
}
componentDidUpdate() {
console.log(`componentDidUpdate 方法`)
}
componentWillUnmount() {
console.log(`componentWillUnmount 方法`)
}
handleClick() {
console.log(`点击了【按钮】`);
this.setState({
name: 'vue'
})
}
render() {
console.log(`render 方法`)
return (
<div>
<button onClick={() => this.handleClick()}>按钮</button>
<br />
<span>
{this.props.title} {this.state.name}
</span>
</div>
)
}
}
export default App;
运行结果:
App.js:6 defaultProps 初始期
App.js:15 this.state constructor时期
App.js:22 componentWillMount 方法
App.js:58 render 方法
App.js:26 componentDidMount 方法
App.js:51 点击了【按钮】
App.js:34 shouldComponentUpdate 方法
App.js:39 componentWillUpdate 方法
App.js:58 render 方法
App.js:43 componentDidUpdate 方法
父组件变化(props)的情况:
src/App.js
import Child from './Child';
class App extends Component {
static defaultProps = {
title: (() => {
console.log(`defaultProps 初始期`)
return 'app';
})()
}
constructor(props) {
super(props);
this.state = {
name: (() => {
console.log(`this.state constructor时期`);
return 'react'
})()
}
}
componentWillMount() {
console.log(`componentWillMount 方法`)
}
componentDidMount() {
console.log(`componentDidMount 方法`)
}
componentWillReceiveProps() {
console.log(`componentWillReceiveProps 方法`)
}
shouldComponentUpdate() {
console.log(`shouldComponentUpdate 方法`)
return true;
}
componentWillUpdate() {
console.log(`componentWillUpdate 方法`)
}
componentDidUpdate() {
console.log(`componentDidUpdate 方法`)
}
componentWillUnmount() {
console.log(`componentWillUnmount 方法`)
}
handleClick() {
console.log(`点击了【按钮】`);
this.setState({
name: 'vue'
})
}
render() {
console.log(`render 方法`)
return (
<div>
<button onClick={() => this.handleClick()}>按钮</button>
<br />
<Child title={this.state.name}/>
</div>
)
}
}
export default App;
src/Child.jsx
class Child extends Component {
constructor(props) {
super(props);
console.log(`constructor 方法`)
}
componentWillMount() {
console.log(`componentWillMount 方法`)
}
componentDidMount() {
console.log(`componentDidMount 方法`)
}
componentWillReceiveProps() {
console.log(`componentWillReceiveProps 方法`)
}
shouldComponentUpdate() {
console.log(`shouldComponentUpdate 方法`)
return true;
}
componentWillUpdate() {
console.log(`componentWillUpdate 方法`)
}
componentDidUpdate() {
console.log(`componentDidUpdate 方法`)
}
componentWillUnmount() {
console.log(`componentWillUnmount 方法`)
}
render() {
console.log(`render 方法`)
return (
<div>
{this.props.title}
</div>
)
}
}
export default Child;
运行结果:
App.js:7 defaultProps 初始期
App.js:16 this.state constructor时期
App.js:23 componentWillMount 方法
App.js:59 render 方法
Child.jsx:7 constructor 方法
Child.jsx:11 componentWillMount 方法
Child.jsx:40 render 方法
Child.jsx:15 componentDidMount 方法
App.js:27 componentDidMount 方法
App.js:52 点击了【按钮】
App.js:35 shouldComponentUpdate 方法
App.js:40 componentWillUpdate 方法
App.js:59 render 方法
Child.jsx:19 componentWillReceiveProps 方法
Child.jsx:23 shouldComponentUpdate 方法
Child.jsx:28 componentWillUpdate 方法
Child.jsx:40 render 方法
Child.jsx:32 componentDidUpdate 方法
App.js:44 componentDidUpdate 方法
卸载期演示:
src/App.js
import Child from './Child';
class App extends Component {
static defaultProps = {
title: (() => {
console.log(`defaultProps 初始期`)
return 'app';
})()
}
constructor(props) {
super(props);
this.state = {
name: (() => {
console.log(`this.state constructor时期`);
return 'react'
})()
}
}
componentWillMount() {
console.log(`componentWillMount 方法`)
}
componentDidMount() {
console.log(`componentDidMount 方法`)
}
componentWillReceiveProps() {
console.log(`componentWillReceiveProps 方法`)
}
shouldComponentUpdate() {
console.log(`shouldComponentUpdate 方法`)
return true;
}
componentWillUpdate() {
console.log(`componentWillUpdate 方法`)
}
componentDidUpdate() {
console.log(`componentDidUpdate 方法`)
}
componentWillUnmount() {
console.log(`componentWillUnmount 方法`)
}
handleClick() {
console.log(`点击了【按钮】`);
this.setState({
name: 'vue'
})
}
render() {
console.log(`render 方法`)
return (
<div>
<button onClick={() => this.handleClick()}>按钮</button>
<br />
{ this.state.name === 'react' ? <Child title={this.state.name}/> : null }
</div>
)
}
}
export default App;
运行结果:
App.js:7 defaultProps 初始期
App.js:16 this.state constructor时期
App.js:23 componentWillMount 方法
App.js:59 render 方法
Child.jsx:7 constructor 方法
Child.jsx:14 componentWillMount 方法
Child.jsx:46 render 方法
Child.jsx:18 componentDidMount 方法
App.js:27 componentDidMount 方法
App.js:52 点击了【按钮】
App.js:35 shouldComponentUpdate 方法
App.js:40 componentWillUpdate 方法
App.js:59 render 方法
Child.jsx:42 componentWillUnmount 方法
App.js:44 componentDidUpdate 方法
各个回调方法的特性
constructor:
constructor函数是在对应组件初始化时调用的构造方法,构造方法就是该组件的出生方法,对应的对象只能出生一次,所以对应的实例组件一生只能调用一次,除非销毁重新生成。该方法的执行时间点是静态资源初始化执行后(static修饰的属性),componentWillMount方法执行前执行。constructor方法带有一个参数是props,参数props是父级中调用该组件时设置的属性集对象。该方法中第一行必须调用 super(props); 因为实现的组件都是继承自React.Compent对象,调用这个方法才能实现父组件props变化时自身渲染结果随之改变。
特性:
• 参数props父级传递下来的props对象
• constructor中必须写super(props)
• 组件初始化的时候调用,整个生命周期中只调用一次
• 在类中的静态资源加载完后执行(static defaultProps就是静态资源)
用途:
该方法的主要用途是用来初始化组件中的属性和定义属性的。所以我们一般都在这个方法中定义state中的属性,或定义一下实例变量。
componentWillMount
componentWillMount() 这个生命周期方法是React的第一个生命周期方法,该方法在组件对象的基础属性及方法都初始化完成后调用,调用这个方法就是说React开始准备接管这个对象了。
特性:
• 在组件挂载到DOM前调用,且只会被调用一次
• 调用this.setState不会引起组件重新渲染(此时还没有挂载到DOM上)
用途:
该方法中主要是初始化一下数据或在组件初始化的时候去请求数据。
componentDidMount
componentDidMount() 这个生命周期方法应该是用的最多的,一般用在进入页面后,数据初始化。componentDidMount与componentWillMount的区别是:componentWillMount是在render方法前调用的,componentDidMount是在render方法后调用的,render方法后对应的该组件就挂载到DOM上了,就可以完全被react接管了,此时可以调用this.setState方法了。
特性:
• 组件挂载到DOM后调用,且只会被调用一次
• 挂载到DOM后调用this.setState就会引起组件重新渲染
用途:
该方法中与componentWillMount用法差不多,但是这个方法中可以调用this.setState,可以重新渲染界面。
componentWillReceiveProps
componentWillReceiveProps(nextProps) 这个生命周期的方法是在组件挂载到DOM后属性变化后调用的。组件中的属性是由父组件中传递过来的值,在这个方法中可以判断父组件中传过来的值和该组件内值是否相等来判断是否指定属性改变了,来处理特定属性的行为。
特性:
• 参数是nextProps改变后的props对象
• 调用 this.setState不会引起第二次渲染,所以可以在此函数中根据props的变化设置state的值
• 当前组件中的this.props还是原来的值,还没有变化
用途:
该方法主要是来监控属性props的变化的,对特殊属性props的变化做出特别处理。可以过滤出对应属性变化来重新渲染组件,防止组件属性改变每次都渲染组件。
shouldComponentUpdate
shouldComponentUpdate(nextProps, nextState) 这个生命周期的方法是在props和state属性变化后都会调用的方法,用来判断是否需要重新渲染。此方法中的返回值用来决定是否重新渲染,返回true表示需要重新渲染,返回false反之。此方法返回true后会调用componentWillUpdate方法。
特性:
• 参数nextProps、nextState 分别表示变化后的props和state
• 当前组件中的this.props和this.state还是原来的值,还没有变化
• 可比较this.props、this.state和nextProps、nextState 中的值是否有变化
• 此函数return一个布尔值,表示是否需要重新渲染DOM
用途:
我们可以通过shouldComponentUpdate生命周期函数来来判断当前组件所在的props、state和context发生改变时,当前组件还是否需要进行更新操作(可以认为为当前组件自定义一个diff算法),以达到性能的最大优化。
componentWillUpdate
componentWillUpdate(nextProps, nextState) 这个生命周期的方法是在shouldComponentUpdate方法后调用,此方法调用后就会去调用render方法重新渲染界面。此方法中的参数是props变化后的值(父组件传递进来的值),该组件中的props还是原来的值还没有改变。
特性:
• 参数nextProps、 nextState 分别表示变化后的props和state
• 当前组件中的this.props和this.state还是原来的值,还没有变化
• 此方法在调用render方法前执行
用途:
DOM重新渲染前调用,用来查看界面最后渲染时值的前后变化。
componentDidUpdate
componentDidUpdate(prevProps, prevState) 这个生命周期的方法是在componentWillUpdate方法后调用过render后再调用。此方法调用后表示一个渲染过程完成。
特性:
• 参数prevProps, prevState 分别表示变化前的props和state
• 当前组件中的this.props和this.state的值已经变化
• 此方法掉用render方法后执行
用途:
DOM重新渲染后调用,可以用了查看渲染后属性值的前后变化。
componentWillUnmount
componentWillUnmount() 这个生命周期的方法是在组件销毁前调用。
特性:
• 此方法在组件被卸载前调用,可以在这里执行一些清理工作
用途:
组件销毁前做一些清理工作。如:clearTimeout, clearInterval
render
render() 方法用来重新渲染界面。
特性:
• 在componentWillMount后,componentDidMount前会被调用一次
• 在componentWillUpdate后,componentDidUpdate前会被调用
• 不能执行this.setState(会死循环)